Attribute VB_Name = "Vtests"
Option Explicit
Option Compare Text

' $Date: 2023/01/01 11:29:46 $

Dim nRet As Long

Public Sub V_Test_ASN1_TextDump()
    Debug.Print "Testing ASN1_TextDump code ..."
    Dim nRet As Long
    Dim strInputFile As String
    Dim strOutFile As String
    
    strInputFile = "smallca.cer"
    strOutFile = "dumpasn1-smallca.cer.txt"
    Debug.Print "File: " & strInputFile
    nRet = ASN1_TextDump(strOutFile, strInputFile, 0)
    Debug.Print "ASN1_TextDump returns " & nRet
    ShowTextFile strOutFile
    ' Pass input as a string
    strInputFile = "MAQwAgUA"
    strOutFile = "dumpasn1.txt"
    Debug.Print "Input: " & strInputFile
    nRet = ASN1_TextDump(strOutFile, strInputFile, 0)
    Debug.Print "ASN1_TextDump returns " & nRet
    ShowTextFile strOutFile
    ' Again with no comments
    nRet = ASN1_TextDump(strOutFile, strInputFile, PKI_ASN1_NOCOMMENTS)
    Debug.Print "ASN1_TextDump returns " & nRet
    ShowTextFile strOutFile

End Sub

Public Sub V_Test_ASN1_TextDumpToString()
    Debug.Print "Testing ASN1_TextDumpToString code ..."
    Dim strInputFile As String
    Dim strBuffer As String
    Dim nChars As Long
    
    ' Pass input as a string
    strInputFile = "MAQwAgUA"
    Debug.Print "Input: " & strInputFile
    ' Query for required length
    nChars = ASN1_TextDumpToString("", 0, strInputFile, "", 0)
    Debug.Print "ASN1_TextDumpToString returns " & nChars
    ' Dimension output buffer
    strBuffer = String(nChars, " ")
    nChars = ASN1_TextDumpToString(strBuffer, Len(strBuffer), strInputFile, "", 0)
    Debug.Print strBuffer
    ' Again with no comments
    strBuffer = String(nChars, " ")
    nChars = ASN1_TextDumpToString(strBuffer, Len(strBuffer), strInputFile, "", PKI_ASN1_NOCOMMENTS)
    Debug.Print "ASN1_TextDumpToString returns " & nChars
    Debug.Print Left(strBuffer, nChars)

End Sub

Public Sub V_Test_ASN1_TextDumpToString2()
    Debug.Print "Testing ASN1_TextDumpToString vbacode ..."
    Debug.Print x509TextDumpToString("AliceRSASignByCarl.cer")
    Debug.Print x509QueryCert("AliceRSASignByCarl.cer", "subjectName")
    Debug.Print asn1TextDumpToString("AliceRSASignByCarl.cer")

End Sub

Public Sub V_Test_ASN1_TextDumpToString3()
    Debug.Print "Testing ASN1_TextDumpToString vbacode ..."
    Dim strInput As String
    Dim strOutput As String
    strInput = "MAQwAgUA"
    Debug.Print "Input: " & strInput
    strOutput = asn1TextDumpToString(strInput)
    Debug.Print strOutput
    Debug.Print asn1TextDumpToString(strInput, PKI_ASN1_NOCOMMENTS)

End Sub

Public Sub V_Test_ASN1_Type()
    Debug.Print "Testing ASN1_Type code ..."
    Dim nChars As Long
    Dim strTypeName As String
    
    ' Output guaranteed not to be longer than PKI_ASN1_TYPE_MAXCHARS characters
    strTypeName = String(PKI_ASN1_TYPE_MAXCHARS, " ")
    nChars = ASN1_Type(strTypeName, Len(strTypeName), "AliceRSASignByCarl.cer", 0)
    If nChars > 0 Then Debug.Print Left(strTypeName, nChars)
    
    strTypeName = String(PKI_ASN1_TYPE_MAXCHARS, " ")
    nChars = ASN1_Type(strTypeName, Len(strTypeName), "AlicePrivRSASign.pri", 0)
    If nChars > 0 Then Debug.Print Left(strTypeName, nChars)
    
    strTypeName = String(PKI_ASN1_TYPE_MAXCHARS, " ")
    nChars = ASN1_Type(strTypeName, Len(strTypeName), "BobPrivRSAEncrypt.p8e", 0)
    If nChars > 0 Then Debug.Print Left(strTypeName, nChars)
      
    strTypeName = String(PKI_ASN1_TYPE_MAXCHARS, " ")
    nChars = ASN1_Type(strTypeName, Len(strTypeName), "rfc3280bis_CRL.crl", 0)
    If nChars > 0 Then Debug.Print Left(strTypeName, nChars)

End Sub

Public Sub V_Test_ASN1_Type2()
    Debug.Print "Testing ASN1_Type vbacode ..."
    Debug.Print asn1Type("AliceRSASignByCarl.cer", 0)
    Debug.Print asn1Type("BobPrivRSAEncrypt.p8e", 0)
    Debug.Print asn1Type("bad.file", 0)
End Sub

Public Sub V_Test_CIPHER_Bytes()
    Debug.Print "Testing CIPHER_Bytes code ..."
    Dim nRet As Long
    Dim strOutput As String
    Dim strInput As String
    Dim sCorrect As String
    Dim abKey()  As Byte
    Dim abInitV() As Byte
    Dim abResult() As Byte
    Dim abData() As Byte
    Dim abCheck() As Byte
    Dim nDataLen As Long
    
    ' Set up input in byte arrays
    strInput = "Now is the time for all good men"
    sCorrect = "C3153108A8DD340C0BCB1DFE8D25D2320EE0E66BD2BB4A313FB75C5638E9E177"
    abKey = cnvBytesFromHexStr("0123456789ABCDEFF0E1D2C3B4A59687")
    abInitV = cnvBytesFromHexStr("FEDCBA9876543210FEDCBA9876543210")
    abData = StrConv(strInput, vbFromUnicode)
    nDataLen = UBound(abData) - LBound(abData) + 1
    
    ' Pre-dimension output array
    ReDim abResult(nDataLen - 1)
    
    Debug.Print "KY=" & cnvHexStrFromBytes(abKey)
    Debug.Print "IV=" & cnvHexStrFromBytes(abInitV)
    Debug.Print "PT=" & strInput
    Debug.Print "PT=" & cnvHexStrFromBytes(abData)
    ' Encrypt in one-off process (abResult <-- abData)
    nRet = CIPHER_Bytes(ENCRYPT, abResult(0), abData(0), nDataLen, _
        abKey(0), abInitV(0), "aes128-cbc", 0)
    Debug.Print "CIPHER_Bytes(ENCRYPT) returns " & nRet
    Debug.Print "CT=" & cnvHexStrFromBytes(abResult)
    Debug.Print "OK=" & sCorrect
    
    ' Now decrypt back (abCheck <-- abResult)
    ReDim abCheck(nDataLen - 1)
    nRet = CIPHER_Bytes(DECRYPT, abCheck(0), abResult(0), nDataLen, _
        abKey(0), abInitV(0), "", PKI_BC_AES128 + PKI_MODE_CBC)
    Debug.Print "CIPHER_Bytes(DECRYPT) returns " & nRet
    ' And decode back from a byte array into a string
    Debug.Print "P'=" & cnvHexStrFromBytes(abCheck)
    strOutput = StrConv(abCheck(), vbUnicode)
    Debug.Print "P'=" & strOutput

End Sub

Public Sub V_Test_CIPHER_DecryptAEAD()
    Debug.Print "Testing CIPHER_DecryptAEAD code ..."
    Dim key() As Byte
    Dim iv() As Byte
    Dim pt() As Byte
    Dim ct() As Byte
    Dim strOK As String
    Dim ptlen As Long
    Dim ctlen As Long
    Dim keylen As Long
    Dim ivlen As Long
    
    ' GCM Test Case #03 (AES-128)
    key = cnvBytesFromHexStr("feffe9928665731c6d6a8f9467308308")
    iv = cnvBytesFromHexStr("cafebabefacedbaddecaf888")
    ct = cnvBytesFromHexStr("42831ec2217774244b7221b784d0d49ce3aa212f2c02a4e035c17e2329aca12e21d514b25466931c7d8f6a5aac84aa051ba30b396a0aac973d58e091473f59854d5c2af327cd64a62cf35abd2ba6fab4")
    strOK = "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255"
    keylen = UBound(key) + 1
    ivlen = UBound(iv) + 1
    ctlen = UBound(ct) + 1
    Debug.Print "KY=" & cnvHexStrFromBytes(key)
    Debug.Print "IV=" & cnvHexStrFromBytes(iv)
    Debug.Print "CT=" & cnvHexStrFromBytes(ct)
    
    ' 1. Find out required output length
    ptlen = CIPHER_DecryptAEAD(ByVal 0&, 0, ct(0), ctlen, key(0), keylen, iv(0), ivlen, ByVal 0&, 0, PKI_AEAD_AES_128_GCM)
    Debug.Print "CIPHER_DecryptAEAD returns " & ptlen
    ' 1a. Cope with error
    If (ptlen < 0) Then
        Debug.Print pkiErrorLookup(ptlen)
        Exit Sub
    End If
    ' 2. Allocate the output buffer, coping with possible zero-length output, then decrypt
    pt = vbNullString   ' Default empty array
    If ptlen > 0 Then
        ReDim pt(ptlen - 1)
        ptlen = CIPHER_DecryptAEAD(pt(0), ptlen, ct(0), ctlen, key(0), keylen, iv(0), ivlen, ByVal 0&, 0, PKI_AEAD_AES_128_GCM)
    End If
    Debug.Print "PT=" & cnvHexStrFromBytes(pt)
    Debug.Print "OK=" & strOK

End Sub

Public Sub V_Test_CIPHER_DecryptAEAD2()
    Debug.Print "Testing CIPHER_DecryptAEAD vbacode ..."
    Dim key() As Byte
    Dim iv() As Byte
    Dim pt() As Byte
    Dim ct() As Byte
    Dim strOK As String
    Dim ptlen As Long
    Dim ctlen As Long
    Dim keylen As Long
    Dim ivlen As Long
    
    ' GCM Test Case #03 (AES-128)
    key = cnvBytesFromHexStr("feffe9928665731c6d6a8f9467308308")
    iv = cnvBytesFromHexStr("cafebabefacedbaddecaf888")
    ct = cnvBytesFromHexStr("42831ec2217774244b7221b784d0d49ce3aa212f2c02a4e035c17e2329aca12e21d514b25466931c7d8f6a5aac84aa051ba30b396a0aac973d58e091473f59854d5c2af327cd64a62cf35abd2ba6fab4")
    strOK = "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255"
    keylen = UBound(key) + 1
    ivlen = UBound(iv) + 1
    ctlen = UBound(ct) + 1
    Debug.Print "KY=" & cnvHexStrFromBytes(key)
    Debug.Print "IV=" & cnvHexStrFromBytes(iv)
    Debug.Print "CT=" & cnvHexStrFromBytes(ct)
    
    ' 1. Find out required output length
    ptlen = CIPHER_DecryptAEAD(ByVal 0&, 0, ct(0), ctlen, key(0), keylen, iv(0), ivlen, ByVal 0&, 0, PKI_AEAD_AES_128_GCM)
    Debug.Print "CIPHER_DecryptAEAD returns " & ptlen
    ' 1a. Cope with error
    If (ptlen < 0) Then
        Debug.Print pkiErrorLookup(ptlen)
        Exit Sub
    End If
    ' 2. Allocate the output buffer, coping with possible zero-length output, then decrypt
    pt = vbNullString   ' Default empty array
    If ptlen > 0 Then
        ReDim pt(ptlen - 1)
        ptlen = CIPHER_DecryptAEAD(pt(0), ptlen, ct(0), ctlen, key(0), keylen, iv(0), ivlen, ByVal 0&, 0, PKI_AEAD_AES_128_GCM)
    End If
    Debug.Print "PT=" & cnvHexStrFromBytes(pt)
    Debug.Print "OK=" & strOK
    
    ' II.Using New wrapper
    ' Must dimension any optional empty byte array
    Dim lpAAD() As Byte
    
    pt = cipherDecryptAEAD(ct, key, iv, lpAAD, PKI_AEAD_AES_128_GCM)
    Debug.Print "PT=" & cnvHexStrFromBytes(pt)
    

End Sub

Public Sub V_Test_CIPHER_DecryptAEAD3()
    Debug.Print "Testing CIPHER_DecryptAEAD vbacode ..."
    Dim key() As Byte
    Dim iv() As Byte
    Dim pt() As Byte
    Dim ct() As Byte
    Dim strOK As String
    
    ' GCM Test Case #03 (AES-128)
    key = cnvBytesFromHexStr("feffe9928665731c6d6a8f9467308308")
    iv = cnvBytesFromHexStr("cafebabefacedbaddecaf888")
    ct = cnvBytesFromHexStr("42831ec2217774244b7221b784d0d49ce3aa212f2c02a4e035c17e2329aca12e21d514b25466931c7d8f6a5aac84aa051ba30b396a0aac973d58e091473f59854d5c2af327cd64a62cf35abd2ba6fab4")
    strOK = "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255"
    Dim lpAAD() As Byte ' Declare empty array for NULL input
    pt = cipherDecryptAEAD(ct, key, iv, lpAAD, PKI_AEAD_AES_128_GCM)
    Debug.Print "PT=" & cnvHexStrFromBytes(pt)
    Debug.Print "OK=" & strOK
End Sub

Public Sub V_Test_CIPHER_DecryptBytes()
    Debug.Print "Testing CIPHER_DecryptBytes code ..."
    Dim key() As Byte
    Dim iv() As Byte
    Dim ct() As Byte
    Dim ok() As Byte
    Dim dt() As Byte
    Dim ctlen As Long
    Dim dtlen As Long
    Dim keylen As Long
    Dim ivlen As Long
    Dim algstr As String
    
    ' INPUT for known test vector
    algstr = "Aes128/CBC/OneAndZeroes"
    Debug.Print algstr
    key = cnvBytesFromHexStr("0123456789ABCDEFF0E1D2C3B4A59687")
    iv = cnvBytesFromHexStr("FEDCBA9876543210FEDCBA9876543210")
    keylen = UBound(key) + 1
    ivlen = UBound(iv) + 1
    Debug.Print ("KY=" & cnvHexStrFromBytes(key))
    Debug.Print ("IV=" & cnvHexStrFromBytes(iv))
    ct = cnvBytesFromHexStr("C3153108A8DD340C0BCB1DFE8D25D2320EE0E66BD2BB4A313FB75C5638E9E1771D4CDA34FBFB7E74B321F9A2CF4EA61B")
    ctlen = UBound(ct) + 1
    Debug.Print ("CT=" & cnvHexStrFromBytes(ct))
    ' OK = "Now is the time for all good men to"
    ok = cnvBytesFromHexStr("4E6F77206973207468652074696D6520666F7220616C6C20676F6F64206D656E20746F")
    
    ' DECRYPT - OLD METHOD
    Debug.Print "Decrypt - old method with truncation"
    ' 1. Set output buffer to same length as input (final output will always be shorter for CBC mode)
    dtlen = ctlen
    ReDim dt(dtlen - 1)
    ' 2. Perform decryption including padding into output buffer
    dtlen = CIPHER_DecryptBytes(dt(0), dtlen, ct(0), ctlen, key(0), keylen, iv(0), ivlen, algstr, 0)
    Debug.Print "CIPHER_DecryptBytes returns " & dtlen
    Debug.Assert dtlen > 0
    ' 3. Re-dimension the output to the correct length
    ReDim Preserve dt(dtlen - 1)
    
    Debug.Print ("DT=" & cnvHexStrFromBytes(dt))
    Debug.Print ("DT='" & StrConv(dt, vbUnicode) + "'")
    
    ' DECRYPT - NEW METHOD [v12.3]
    Debug.Print "Decrypt - new method with exact length"
    ' 1. Find exact output length using null/zero-length output
    dtlen = CIPHER_DecryptBytes(ByVal 0&, 0, ct(0), ctlen, key(0), keylen, iv(0), ivlen, algstr, 0)
    Debug.Print "CIPHER_DecryptBytes(NULL) returns " & dtlen
    Debug.Assert dtlen > 0
    ' 2. Dimension output buffer to exact length
    ReDim dt(dtlen - 1)
    ' 3. Perform decryption - no need to truncate
    dtlen = CIPHER_DecryptBytes(dt(0), dtlen, ct(0), ctlen, key(0), keylen, iv(0), ivlen, algstr, 0)
    Debug.Print "CIPHER_DecryptBytes returns " & dtlen
    Debug.Assert dtlen > 0
    
    Debug.Print ("DT=" & cnvHexStrFromBytes(dt))
    Debug.Print ("DT='" & StrConv(dt, vbUnicode) + "'")
    
    Debug.Print "Check actual padding by decrypting with NoPadding..."
    algstr = "Aes128/CBC/NoPadding"
    Debug.Print algstr
    dtlen = ctlen
    ReDim dt(dtlen - 1)
    dtlen = CIPHER_DecryptBytes(dt(0), dtlen, ct(0), ctlen, key(0), keylen, iv(0), ivlen, algstr, 0)
    Debug.Print "CIPHER_DecryptBytes(NoPadding) returns " & dtlen
    Debug.Print ("DT=" & cnvHexStrFromBytes(dt))

End Sub

Public Sub V_Test_CIPHER_DecryptBytes2()
    Debug.Print "Testing CIPHER_DecryptBytes code ..."
    Dim strCipherValue As String
    Dim strPlain As String
    Dim pt() As Byte
    Dim ptlen As Long
    Dim ct() As Byte
    Dim ctlen As Long
    Dim key() As Byte
    Dim keylen As Long
    Dim iv() As Byte
    Dim ivlen As Long
    Dim nRet As Long
    Dim strDT As String
    Dim dt() As Byte
    Dim dtlen As Long
    
    ' The plaintext to encrypt...
    strPlain = "<encryptme>hello world</encryptme>"
    Debug.Print "PT='" & strPlain & "'"
    
    ' We need this as a byte array...
    pt = StrConv(strPlain, vbFromUnicode)
    Debug.Print "HEX(PT)=" & cnvHexStrFromBytes(pt)
    ptlen = UBound(pt) + 1
    Debug.Print "Len(PT)=" & ptlen
    
    ' 128-bit AES key
    ' (Usually generated at random but here we use a fixed test one)
    key = cnvBytesFromHexStr("6162636465666768696A6B6C6D6E6F70")
    keylen = UBound(key) + 1
    Debug.Print "HEX(KEY)=" & cnvHexStrFromBytes(key)
    
    ' Generate a random 128-bit IV for AES encryption
    ivlen = PKI_BLK_AES_BYTES
    ReDim iv(ivlen - 1)
    nRet = RNG_Bytes(iv(0), ivlen, "", 0)
    Debug.Print "HEX(IV)=" & cnvHexStrFromBytes(iv)
    
    ' Encrypt using AES-128 with IV prefixed to ciphertext
    
    ' How many bytes in the encrypted output?
    ctlen = CIPHER_EncryptBytes(ByVal 0&, 0, pt(0), ptlen, key(0), keylen, iv(0), ivlen, "aes128/cbc/pkcs5", PKI_IV_PREFIX)
    Debug.Print "Len(IV|CT)=" & ctlen
    Debug.Assert (ctlen > 0)
    ' Allocate the buffer
    ReDim ct(ctlen - 1)
    ' Encrypt to output buffer
    ctlen = CIPHER_EncryptBytes(ct(0), ctlen, pt(0), ptlen, key(0), keylen, iv(0), ivlen, "aes128/cbc/pkcs5", PKI_IV_PREFIX)
    Debug.Assert (ctlen > 0)
    Debug.Print "IV|CT=" & cnvHexStrFromBytes(ct)
    
    ' Encode CT using base64
    strCipherValue = cnvB64StrFromBytes(ct)
    
    ' Output the CipherValue element
    ' (Note this will be different each time)
    Debug.Print "<CipherValue>" & strCipherValue & "</CipherValue>"
    
    ' ------------------------------------------
    ' PART 2 - decrypt the given ciphertext
    
    Debug.Print
    Debug.Print "DECRYPTING..."
    ' INPUT: strCipherValue, key
    ' Decode base64 to byte array
    ct = cnvBytesFromB64Str(strCipherValue)
    ctlen = UBound(ct) + 1
    Debug.Print "IV|CT=" & cnvHexStrFromBytes(ct)
    ' Find decrypted output length - new behaviour in [v12.3] (previously needed to truncate)
    dtlen = CIPHER_DecryptBytes(ByVal 0&, 0, ct(0), ctlen, key(0), keylen, ByVal 0&, 0, "aes128/cbc/pkcs5", PKI_IV_PREFIX)
    Debug.Assert (dtlen > 0)
    ReDim dt(dtlen - 1)
    ' Note we don't need to specify the IV: it is included in the prefix
    dtlen = CIPHER_DecryptBytes(dt(0), dtlen, ct(0), ctlen, key(0), keylen, ByVal 0&, 0, "aes128/cbc/pkcs5", PKI_IV_PREFIX)
    Debug.Print "Len(DT)=" & dtlen
    Debug.Assert (dtlen >= 0)
    
    Debug.Print "DT=" & cnvHexStrFromBytes(dt)
    ' Convert from bytes to string
    strDT = StrConv(dt, vbUnicode)
    Debug.Print "DT='" & strDT & "'"

End Sub

Public Sub V_Test_CIPHER_DecryptHex()
    Debug.Print "Testing CIPHER_DecryptHex code ..."
    Dim strKey As String
    Dim strIV As String
    Dim strPlain As String
    Dim strCipher As String
    Dim strOK As String
    Dim strAlg As String
    Dim nChars As Long
    
    strAlg = "Aes128/CBC/OneAndZeroes"
    Debug.Print strAlg
    strKey = "0123456789ABCDEFF0E1D2C3B4A59687"
    strIV = "FEDCBA9876543210FEDCBA9876543210"
    Debug.Print "KY=" & strKey
    Debug.Print "IV=" & strIV
    strCipher = "C3153108A8DD340C0BCB1DFE8D25D2320EE0E66BD2BB4A313FB75C5638E9E1771D4CDA34FBFB7E74B321F9A2CF4EA61B"
    Debug.Print "CT=" & strCipher
    ' Correct result
    strOK = "4E6F77206973207468652074696D6520666F7220616C6C20676F6F64206D656E20746F"
    
    ' 1. Find out how long an output buffer we need
    nChars = CIPHER_DecryptHex(vbNullString, 0, strCipher, strKey, strIV, strAlg, 0)
    Debug.Print "CIPHER_DecryptHex returns " & nChars
    Debug.Assert nChars > 0
    ' 2. Allocate the buffer
    strPlain = String(nChars, " ")
    ' 3. Decrypt to output buffer
    nChars = CIPHER_DecryptHex(strPlain, nChars, strCipher, strKey, strIV, strAlg, 0)
    
    Debug.Print "PT=" & strPlain
    Debug.Print "OK=" & strOK
    
    ' PART 2 - CT includes IV prefix
    strCipher = "FEDCBA9876543210FEDCBA9876543210C3153108A8DD340C0BCB1DFE8D25D2320EE0E66BD2BB4A313FB75C5638E9E1771D4CDA34FBFB7E74B321F9A2CF4EA61B"
    Debug.Print "IV||CT=" & strCipher
    nChars = CIPHER_DecryptHex(vbNullString, 0, strCipher, strKey, strIV, strAlg, PKI_IV_PREFIX)
    Debug.Print "CIPHER_DecryptHex(PKI_IV_PREFIX) returns " & nChars
    Debug.Assert nChars > 0
    strPlain = String(nChars, " ")
    nChars = CIPHER_DecryptHex(strPlain, nChars, strCipher, strKey, strIV, strAlg, PKI_IV_PREFIX)
    
    Debug.Print "PT=" & strPlain
    Debug.Print "PT='" & cnvStringFromHexStr(strPlain) & "'"

End Sub

Public Sub V_Test_CIPHER_DecryptHex2()
    Debug.Print "Testing CIPHER_DecryptHex vbacode ..."
    Dim strKeyHex As String
    Dim strIvHex As String
    Dim strPlainHex As String
    Dim strCipherHex As String
    strKeyHex = "0123456789ABCDEFF0E1D2C3B4A59687"
    strIvHex = "FEDCBA9876543210FEDCBA9876543210"
    strCipherHex = "C3153108A8DD340C0BCB1DFE8D25D2320EE0E66BD2BB4A313FB75C5638E9E1771D4CDA34FBFB7E74B321F9A2CF4EA61B"
    strPlainHex = cipherDecryptHex(strCipherHex, strKeyHex, strIvHex, "Aes128/CBC/OneAndZeroes")
    Debug.Print "PT=" & strPlainHex
    Debug.Print "PT='" & cnvStringFromHexStr(strPlainHex) & "'"

End Sub

Public Sub V_Test_CIPHER_EncryptAEAD()
    Debug.Print "Testing CIPHER_EncryptAEAD code ..."
    Dim key() As Byte
    Dim iv() As Byte
    Dim pt() As Byte
    Dim ct() As Byte
    Dim strOK As String
    Dim ptlen As Long
    Dim ctlen As Long
    Dim keylen As Long
    Dim ivlen As Long
    
    ' GCM Test Case #03 (AES-128)
    key = cnvBytesFromHexStr("feffe9928665731c6d6a8f9467308308")
    iv = cnvBytesFromHexStr("cafebabefacedbaddecaf888")
    pt = cnvBytesFromHexStr("d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255")
    strOK = "42831ec2217774244b7221b784d0d49ce3aa212f2c02a4e035c17e2329aca12e21d514b25466931c7d8f6a5aac84aa051ba30b396a0aac973d58e091473f59854d5c2af327cd64a62cf35abd2ba6fab4"
    keylen = UBound(key) + 1
    ivlen = UBound(iv) + 1
    ptlen = UBound(pt) + 1
    Debug.Print "KY=" & cnvHexStrFromBytes(key)
    Debug.Print "IV=" & cnvHexStrFromBytes(iv)
    Debug.Print "PT=" & cnvHexStrFromBytes(pt)
    ' 1. Find out how long an output buffer we need
    ctlen = CIPHER_EncryptAEAD(ByVal 0&, 0, pt(0), ptlen, key(0), keylen, iv(0), ivlen, ByVal 0&, 0, PKI_AEAD_AES_128_GCM)
    Debug.Print "CIPHER_EncryptAEAD returns " & ctlen
    Debug.Assert ctlen > 0
    ' 2. Allocate the buffer
    ReDim ct(ctlen - 1)
    ' 3. Encrypt to output buffer (NB tag is appended to the end)
    ctlen = CIPHER_EncryptAEAD(ct(0), ctlen, pt(0), ptlen, key(0), keylen, iv(0), ivlen, ByVal 0&, 0, PKI_AEAD_AES_128_GCM)
    
    Debug.Print "CT=" & cnvHexStrFromBytes(ct)
    Debug.Print "OK=" & strOK
        
    ' Repeat but prepend IV to output
    ctlen = CIPHER_EncryptAEAD(ByVal 0&, 0, pt(0), ptlen, key(0), keylen, iv(0), ivlen, ByVal 0&, 0, PKI_AEAD_AES_128_GCM Or PKI_IV_PREFIX)
    Debug.Print "CIPHER_EncryptAEAD returns " & ctlen
    Debug.Assert ctlen > 0
    ReDim ct(ctlen - 1)
    ctlen = CIPHER_EncryptAEAD(ct(0), ctlen, pt(0), ptlen, key(0), keylen, iv(0), ivlen, ByVal 0&, 0, PKI_AEAD_AES_128_GCM Or PKI_IV_PREFIX)
    
    Debug.Print "IV|CT=" & cnvHexStrFromBytes(ct)

End Sub

Public Sub V_Test_CIPHER_EncryptAEAD2()
    Debug.Print "Testing CIPHER_EncryptAEAD vbacode ..."
    Dim key() As Byte
    Dim iv() As Byte
    Dim pt() As Byte
    Dim ct() As Byte
    Dim lpDummy() As Byte
    ' GCM Test Case #03 (AES-128)
    key = cnvBytesFromHexStr("feffe9928665731c6d6a8f9467308308")
    iv = cnvBytesFromHexStr("cafebabefacedbaddecaf888")
    pt = cnvBytesFromHexStr("d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255")
    ct = cipherEncryptAEAD(pt, key, iv, lpDummy, PKI_AEAD_AES_128_GCM Or PKI_IV_PREFIX)
    Debug.Print "IV|CT=" & cnvHexStrFromBytes(ct)
    Debug.Print "OK=   " & _
        "CAFEBABEFACEDBADDECAF888" & _
    "42831EC2217774244B7221B784D0D49CE3AA212F2C02A4E035C17E2329ACA12E21D514B25466931C7D8F6A5AAC84AA051BA30B396A0AAC973D58E091473F59854D5C2AF327CD64A62CF35ABD2BA6FAB4"

End Sub

Public Sub V_Test_CIPHER_EncryptBytes()
    Debug.Print "Testing CIPHER_EncryptBytes code ..."
    Dim key() As Byte
    Dim iv() As Byte
    Dim pt() As Byte
    Dim ct() As Byte
    Dim ok() As Byte
    Dim ptlen As Long
    Dim ctlen As Long
    Dim keylen As Long
    Dim ivlen As Long
    Dim algstr As String
    
    algstr = "Aes128/CBC/OneAndZeroes"
    Debug.Print algstr
    key = cnvBytesFromHexStr("0123456789ABCDEFF0E1D2C3B4A59687")
    iv = cnvBytesFromHexStr("FEDCBA9876543210FEDCBA9876543210")
    keylen = UBound(key) + 1
    ivlen = UBound(iv) + 1
    Debug.Print "KY=" & cnvHexStrFromBytes(key)
    Debug.Print "IV=" & cnvHexStrFromBytes(iv)
    ' "Now is the time for all good men to"
    pt = cnvBytesFromHexStr("4E6F77206973207468652074696D6520666F7220616C6C20676F6F64206D656E20746F")
    ptlen = UBound(pt) + 1
    ' Correct result
    ok = cnvBytesFromHexStr("C3153108A8DD340C0BCB1DFE8D25D2320EE0E66BD2BB4A313FB75C5638E9E1771D4CDA34FBFB7E74B321F9A2CF4EA61B")
    Debug.Print ("PT=" & cnvHexStrFromBytes(pt))
    Debug.Print ("PT='" & StrConv(pt, vbUnicode) + "'")
    ' 1. Find out how long an output buffer we need
    ctlen = CIPHER_EncryptBytes(0, 0, pt(0), ptlen, key(0), keylen, iv(0), ivlen, algstr, 0)
    Debug.Print "CIPHER_EncryptBytes returns " & ctlen
    ' 2. Allocate the buffer
    ReDim ct(ctlen - 1)
    ' 3. Encrypt to output buffer
    ctlen = CIPHER_EncryptBytes(ct(0), ctlen, pt(0), ptlen, key(0), keylen, iv(0), ivlen, algstr, 0)
    
    Debug.Print "CT=" & cnvHexStrFromBytes(ct)
    Debug.Print "OK=" & cnvHexStrFromBytes(ok)
    
    ' PART 2 - prefix the IV in the output
    ctlen = CIPHER_EncryptBytes(0, 0, pt(0), ptlen, key(0), keylen, iv(0), ivlen, algstr, PKI_IV_PREFIX)
    Debug.Print "CIPHER_EncryptBytes(PKI_IV_PREFIX) returns " & ctlen
    ReDim ct(ctlen - 1)
    ctlen = CIPHER_EncryptBytes(ct(0), ctlen, pt(0), ptlen, key(0), keylen, iv(0), ivlen, algstr, PKI_IV_PREFIX)
    
    Debug.Print "IV||CT=" & cnvHexStrFromBytes(ct)

End Sub

Public Sub V_Test_CIPHER_EncryptBytes2()
    Debug.Print "Testing CIPHER_EncryptBytes vbacode ..."
    Dim key() As Byte
    Dim iv() As Byte
    Dim pt() As Byte
    Dim ct() As Byte
    Dim dt() As Byte
    Dim algstr As String
    
    ' PART 1
    algstr = "Aes128/CBC/OneAndZeroes"
    Debug.Print algstr
    key = cnvBytesFromHexStr("0123456789ABCDEFF0E1D2C3B4A59687")
    iv = cnvBytesFromHexStr("FEDCBA9876543210FEDCBA9876543210")
    ' "Now is the time for all good men to"
    pt = cnvBytesFromHexStr("4E6F77206973207468652074696D6520666F7220616C6C20676F6F64206D656E20746F")
    
    ct = cipherEncryptBytes(pt, key, iv, algstr, 0)
    Debug.Print "CT=" & cnvHexStrFromBytes(ct)
    Debug.Print "OK=C3153108A8DD340C0BCB1DFE8D25D2320EE0E66BD2BB4A313FB75C5638E9E1771D4CDA34FBFB7E74B321F9A2CF4EA61B"
    
    dt = cipherDecryptBytes(ct, key, iv, algstr, 0)
    Debug.Print "dt='" & StrConv(dt, vbUnicode) & "'"
    
    ' PART 2 - Use CTR mode and prefix the IV in the output
    algstr = "Aes128/CTR"
    Debug.Print algstr & " + PREFIX"
    ct = cipherEncryptBytes(pt, key, iv, algstr, PKI_IV_PREFIX)
    Debug.Print "CT=" & cnvHexStrFromBytes(ct)
    dt = cipherDecryptBytes(ct, key, iv, algstr, PKI_IV_PREFIX)
    Debug.Print "dt='" & StrConv(dt, vbUnicode) & "'"
    
    ' PART 3 - Use ECB mode and note we use a dummy empty byte array for the IV
    Dim dummy() As Byte
    algstr = "Aes128/ECB"
    Debug.Print algstr
    ct = cipherEncryptBytes(pt, key, dummy, algstr, 0)
    Debug.Print "CT=" & cnvHexStrFromBytes(ct)
    dt = cipherDecryptBytes(ct, key, dummy, algstr, 0)
    Debug.Print "dt='" & StrConv(dt, vbUnicode) & "'"

End Sub

Public Sub V_Test_CIPHER_EncryptHex()
    Debug.Print "Testing CIPHER_EncryptHex code ..."
    Dim strKey As String
    Dim strIV As String
    Dim strPlain As String
    Dim strCipher As String
    Dim strOK As String
    Dim strAlg As String
    Dim nChars As Long
    
    strAlg = "Aes128/CBC/OneAndZeroes"
    Debug.Print strAlg
    strKey = "0123456789ABCDEFF0E1D2C3B4A59687"
    strIV = "FEDCBA9876543210FEDCBA9876543210"
    Debug.Print "KY=" & strKey
    Debug.Print "IV=" & strIV
    ' "Now is the time for all good men to"
    strPlain = "4E6F77206973207468652074696D6520666F7220616C6C20676F6F64206D656E20746F"
    Debug.Print "PT=" & strPlain
    Debug.Print "PT='" & cnvStringFromHexStr(strPlain) & "'"
    ' Correct result
    strOK = "C3153108A8DD340C0BCB1DFE8D25D2320EE0E66BD2BB4A313FB75C5638E9E1771D4CDA34FBFB7E74B321F9A2CF4EA61B"
    
    ' 1. Find out how long an output buffer we need
    nChars = CIPHER_EncryptHex(vbNullString, 0, strPlain, strKey, strIV, strAlg, 0)
    Debug.Print "CIPHER_EncryptHex returns " & nChars
    Debug.Assert nChars > 0
    ' 2. Allocate the buffer
    strCipher = String(nChars, " ")
    ' 3. Encrypt to output buffer
    nChars = CIPHER_EncryptHex(strCipher, nChars, strPlain, strKey, strIV, strAlg, 0)
    
    Debug.Print "CT=" & strCipher
    Debug.Print "OK=" & strOK
    
    ' PART 2 - prefix the IV in the output
    nChars = CIPHER_EncryptHex(vbNullString, 0, strPlain, strKey, strIV, strAlg, PKI_IV_PREFIX)
    Debug.Print "CIPHER_EncryptHex(PKI_IV_PREFIX) returns " & nChars
    Debug.Assert nChars > 0
    strCipher = String(nChars, " ")
    nChars = CIPHER_EncryptHex(strCipher, nChars, strPlain, strKey, strIV, strAlg, PKI_IV_PREFIX)
    
    Debug.Print "IV||CT=" & strCipher

End Sub

Public Sub V_Test_CIPHER_EncryptHex2()
    Debug.Print "Testing CIPHER_EncryptHex vbacode ..."
    Dim strKeyHex As String
    Dim strIvHex As String
    Dim strPlainHex As String
    Dim strCipherHex As String
    strKeyHex = "0123456789ABCDEFF0E1D2C3B4A59687"
    strIvHex = "FEDCBA9876543210FEDCBA9876543210"
    strPlainHex = "4E6F77206973207468652074696D6520666F7220616C6C20676F6F64206D656E20746F"
    
    ' Get encrypted output directly in hex
    strCipherHex = cipherEncryptHex(strPlainHex, strKeyHex, strIvHex, "Aes128/CBC/OneAndZeroes", 0)
    Debug.Print strCipherHex
    
    ' Same again with bytes
    Dim lpKey() As Byte
    Dim lpIV() As Byte
    Dim lpPlain() As Byte
    Dim lpCipher() As Byte
    lpPlain = StrConv("Now is the time for all good men to", vbFromUnicode)
    lpKey = cnvBytesFromHexStr("0123456789ABCDEFF0E1D2C3B4A59687")
    lpIV = cnvBytesFromHexStr("FEDCBA9876543210FEDCBA9876543210")
    ' Get encrypted output
    lpCipher = cipherEncryptBytes(lpPlain, lpKey, lpIV, "Aes128/CBC/OneAndZeroes", 0)
    Debug.Print cnvHexStrFromBytes(lpCipher)
    
    ' Same again using ECB mode with default PKCS#5 padding
    ' To pass an empty byte array for IV, create a dummy zero-length array
    Dim lpDummy() As Byte
    lpCipher = cipherEncryptBytes(lpPlain, lpKey, lpDummy, "Aes128/ECB", 0)
    Debug.Print cnvHexStrFromBytes(lpCipher)
    
    ' The old way - we need all the byte array lengths
    Dim nBytes As Long
    Dim nDataLen As Long
    Dim nKeyLen As Long
    Dim nIVLen As Long
    nDataLen = cnvBytesLen(lpPlain)
    nKeyLen = cnvBytesLen(lpKey)
    nIVLen = cnvBytesLen(lpIV)
    nBytes = CIPHER_EncryptBytes(ByVal 0&, 0, lpPlain(0), nDataLen, lpKey(0), nKeyLen, lpIV(0), nIVLen, "Aes128/CBC/OneAndZeroes", 0)
    Debug.Assert nBytes > 0
    ReDim lpCipher(nBytes - 1)
    nBytes = CIPHER_EncryptBytes(lpCipher(0), nBytes, lpPlain(0), nDataLen, lpKey(0), nKeyLen, lpIV(0), nIVLen, "Aes128/CBC/OneAndZeroes", 0)
    Debug.Print cnvHexStrFromBytes(lpCipher)
    
    ' Same again with hex using ECB mode with default PKCS#5 padding
    ' To pass a "null" IV in hex, just use the empty string
    strCipherHex = cipherEncryptHex(strPlainHex, strKeyHex, "", "Aes128/ECB", 0)
    Debug.Print strCipherHex
    
    ' Or vbNullString
    strCipherHex = cipherEncryptHex(strPlainHex, strKeyHex, vbNullString, "Aes128/ECB", 0)
    Debug.Print strCipherHex

End Sub

Public Sub V_Test_CIPHER_File()
    Debug.Print "Testing CIPHER_File code ..."
    Const MY_PATH As String = ""
    Dim abKey() As Byte
    Dim abIV() As Byte
    Dim strFileEnc As String
    Dim strFileIn As String
    Dim strFileChk As String
    Dim nRet As Long
    
    ' Construct full path names to files
    strFileIn = MY_PATH & "hello.txt"
    strFileEnc = MY_PATH & "hello.aes128.enc.dat"
    strFileChk = MY_PATH & "hello.aes128.chk.txt"
    
    ' Create the key as an array of bytes
    ' This creates an array of 16 bytes {&HFE, &HDC, ... &H10}
    abKey = cnvBytesFromHexStr("fedcba9876543210fedcba9876543210")
    ' Create the IV at random
    ReDim abIV(PKI_BLK_AES_BYTES - 1)
    Call RNG_Bytes(abIV(0), PKI_BLK_AES_BYTES, "", 0)
    ' Display the IV (this needs to be communicated separately to the recipient)
    Debug.Print "IV=" & cnvHexStrFromBytes(abIV)
    
    ' Encrypt plaintext file to ciphertext using AES-128 in counter (CTR) mode
    ' (This will create a file of exactly the same size as the input)
    nRet = CIPHER_File(ENCRYPT, strFileEnc, strFileIn, abKey(0), abIV(0), "aes128-ctr", 0)
    Debug.Print "CIPHER_File(ENCRYPT) returns " & nRet
    
    ' Now decrypt it
    nRet = CIPHER_File(DECRYPT, strFileChk, strFileEnc, abKey(0), abIV(0), "aes128-ctr", 0)
    Debug.Print "CIPHER_File(DECRYPT) returns " & nRet

End Sub

Public Sub V_Test_CIPHER_FileEncrypt()
    Debug.Print "Testing CIPHER_FileEncrypt code ..."
    Dim abKey() As Byte
    Dim abIV() As Byte
    Dim nKeyLen As Long
    Dim nIVLen As Long
    Dim strFileEnc As String
    Dim strFileIn As String
    Dim strFileChk As String
    Dim strAlgModePad As String
    Dim nRet As Long
    
    ' Construct full path names to files
    strFileIn = "hello.txt"
    strFileEnc = "hello.aes192.enc.dat"
    strFileChk = "hello.aes192.chk.txt"
    
    ' Check input file
    Debug.Print "FileLen('" & strFileIn & "')=" & FileLen(strFileIn)
    
    ' Create the AES-192 key as an array of 24 bytes
    abKey = cnvBytesFromHexStr("fedcba9876543210fedcba98765432101122334455667788")
    nKeyLen = UBound(abKey) + 1
    Debug.Print "KY=" & cnvHexStrFromBytes(abKey)
    Debug.Print "LEN(KY)=" & nKeyLen
    ' Create the IV at random
    ReDim abIV(PKI_BLK_AES_BYTES - 1)
    Call RNG_Bytes(abIV(0), PKI_BLK_AES_BYTES, "", 0)
    ' Display the IV (this will be prepended to the ciphertext in the output file)
    Debug.Print "IV=" & cnvHexStrFromBytes(abIV)
    nIVLen = UBound(abIV) + 1
    Debug.Print "LEN(IV)=" & nIVLen
    
    ' Specify cipher alg/mode/padding
    strAlgModePad = "aes192/CBC/ANSIX923"
    Debug.Print strAlgModePad
    
    ' Encrypt the plaintext file, prefixing the IV
    nRet = CIPHER_FileEncrypt(strFileEnc, strFileIn, abKey(0), nKeyLen, abIV(0), nIVLen, strAlgModePad, PKI_IV_PREFIX)
    Debug.Print "CIPHER_FileEncrypt() returns " & nRet & " (expected 0)"
    Debug.Assert (0 = nRet)
    
    ' Check output file
    Debug.Print "FileLen('" & strFileEnc & "')=" & FileLen(strFileEnc)
    
    ' Now decipher using the IV already prefixed to the ciphertext
    nRet = CIPHER_FileDecrypt(strFileChk, strFileEnc, abKey(0), nKeyLen, 0, 0, strAlgModePad, PKI_IV_PREFIX)
    Debug.Print "CIPHER_FileDecrypt() returns " & nRet & " (expected 0)"
    Debug.Assert (0 = nRet)
    
    ' Check decrypted file - it should match the original plaintext
    Debug.Print "FileLen('" & strFileChk & "')=" & FileLen(strFileChk)
    Debug.Assert (FileLen(strFileChk) = FileLen(strFileIn))

End Sub

Public Sub V_Test_CIPHER_Hex()
    Debug.Print "Testing CIPHER_Hex code ..."
    Dim nRet As Long
    Dim sPlain As String
    Dim sCipher As String
    Dim sCheck As String
    Dim sKey As String
    Dim sInitV As String
    Dim sCorrect As String
    
    sPlain = "5468697320736F6D652073616D706520636F6E74656E742E0808080808080808"
    '         T h i s _ s o m e _ s a m p e _ c o n t e n t .(+padding 8 x 08)
    sKey = "737C791F25EAD0E04629254352F7DC6291E5CB26917ADA32"
    sInitV = "B36B6BFB6231084E"
    sCorrect = "d76fd1178fbd02f84231f5c1d2a2f74a4159482964f675248254223daf9af8e4"
    ' Set output to be same length as input
    sCipher = String(Len(sPlain), " ")
    
    Debug.Print "KY=" & sKey
    Debug.Print "PT=" & sPlain
    ' Encrypt using strAlgAndMode
    nRet = CIPHER_Hex(ENCRYPT, sCipher, Len(sCipher), sPlain, sKey, sInitV, "tdea-cbc", 0)
    Debug.Print "CT=" & sCipher & nRet
    Debug.Print "OK=" & sCorrect
    ' Alternative using nOptions
    nRet = CIPHER_Hex(ENCRYPT, sCipher, Len(sCipher), sPlain, sKey, sInitV, "", PKI_BC_TDEA + PKI_MODE_CBC)
    Debug.Print "CT=" & sCipher & nRet
    Debug.Print "OK=" & sCorrect
    
    ' Decrypt using strAlgAndMode
    sCheck = String(Len(sCipher), " ")
    nRet = CIPHER_Hex(DECRYPT, sCheck, Len(sCheck), sCipher, sKey, sInitV, "tdea-cbc", 0)
    Debug.Print "P'=" & sCheck & nRet
    ' Alternative using nOptions
    sCheck = String(Len(sCipher), " ")
    nRet = CIPHER_Hex(DECRYPT, sCheck, Len(sCheck), sCipher, sKey, sInitV, "", PKI_BC_TDEA + PKI_MODE_CBC)
    Debug.Print "P'=" & sCheck & nRet

End Sub

Public Sub V_Test_CIPHER_KeyWrap()
    Debug.Print "Testing CIPHER_KeyWrap code ..."
    Dim abWK() As Byte
    Dim abKeyData() As Byte
    Dim abKek() As Byte
    Dim nWkLen As Long
    Dim nKdLen As Long
    Dim nKekLen As Long
    
    abKeyData = cnvBytesFromHexStr("00112233 44556677 8899aabb ccddeeff")
    abKek = cnvBytesFromHexStr("c17a44e8 e28d7d64 81d1ddd5 0a3b8914")
    nKdLen = UBound(abKeyData) + 1
    nKekLen = UBound(abKek) + 1
    
    nWkLen = CIPHER_KeyWrap(0, 0, abKeyData(0), nKdLen, abKek(0), nKekLen, PKI_BC_AES128)
    If nWkLen <= 0 Then
        Debug.Print " returns " & nWkLen & ": " & pkiErrorLookup(nWkLen)
        Exit Sub
    End If
    ReDim abWK(nWkLen - 1)
    nWkLen = CIPHER_KeyWrap(abWK(0), nWkLen, abKeyData(0), nKdLen, abKek(0), nKekLen, PKI_BC_AES128)
    Debug.Print "WK=" & cnvHexStrFromBytes(abWK)
    
    abKeyData = cnvBytesFromHexStr("8cbedec4 8d063e1b a46be8e3 69a9c398 d8e30ee5 42bc347c 4f30e928 ddd7db49")
    abKek = cnvBytesFromHexStr("9e84ee99 e6a84b50 c76cd414 a2d2ec05 8af41bfe 4bf3715b f894c8da 1cd445f6")
    nKdLen = UBound(abKeyData) + 1
    nKekLen = UBound(abKek) + 1
    
    nWkLen = CIPHER_KeyWrap(0, 0, abKeyData(0), nKdLen, abKek(0), nKekLen, PKI_BC_AES256)
    If nWkLen <= 0 Then
        Debug.Print " returns " & nWkLen & ": " & pkiErrorLookup(nWkLen)
        Exit Sub
    End If
    ReDim abWK(nWkLen - 1)
    nWkLen = CIPHER_KeyWrap(abWK(0), nWkLen, abKeyData(0), nKdLen, abKek(0), nKekLen, PKI_BC_AES256)
    Debug.Print "WK=" & cnvHexStrFromBytes(abWK)
    
    abKeyData = cnvBytesFromHexStr("84e7f2d8 78f89fcc cd2d5eba fc56daf7 3300f27e f771cd68")
    abKek = cnvBytesFromHexStr("8ad8274e 56f46773 8edd83d4 394e5e29 af7c4089 e4f8d9f4")
    nKdLen = UBound(abKeyData) + 1
    nKekLen = UBound(abKek) + 1
    
    nWkLen = CIPHER_KeyWrap(0, 0, abKeyData(0), nKdLen, abKek(0), nKekLen, PKI_BC_3DES)
    If nWkLen <= 0 Then
        Debug.Print " returns " & nWkLen & ": " & pkiErrorLookup(nWkLen)
        Exit Sub
    End If
    ReDim abWK(nWkLen - 1)
    nWkLen = CIPHER_KeyWrap(abWK(0), nWkLen, abKeyData(0), nKdLen, abKek(0), nKekLen, PKI_BC_3DES)
    Debug.Print "WK=" & cnvHexStrFromBytes(abWK)

End Sub

Public Sub V_Test_CIPHER_KeyWrap2()
    Debug.Print "Testing CIPHER_KeyWrap vbacode ..."
    Dim lpWK() As Byte
    Dim lpKeyData() As Byte
    Dim lpKEK() As Byte
    
    lpKeyData = cnvBytesFromHexStr("00112233 44556677 8899aabb ccddeeff")
    lpKEK = cnvBytesFromHexStr("c17a44e8 e28d7d64 81d1ddd5 0a3b8914")
    ' NB Specific nonzero option required in nOptions
    lpWK = cipherKeyWrap(lpKeyData, lpKEK, PKI_BC_AES128)
    Debug.Print "WK=" & cnvHexStrFromBytes(lpWK)
    Debug.Print "OK=503D75C73630A7B02ECF51B9B29B907749310B77B0B2E054"
    
    ' Now unwrap the KEK
    Dim lpKeyUnwrapped() As Byte
    lpKeyUnwrapped = cipherKeyUnwrap(lpWK, lpKEK, PKI_BC_AES128)
    Debug.Print "KY=" & cnvHexStrFromBytes(lpKeyUnwrapped)
    Debug.Print "OK=00112233445566778899AABBCCDDEEFF"
End Sub

Public Sub V_Test_CIPHER_KeyUnwrap()
    Debug.Print "Testing CIPHER_KeyUnwrap code ..."
    Dim abWK() As Byte
    Dim abKeyData() As Byte
    Dim abKek() As Byte
    Dim nWkLen As Long
    Dim nKdLen As Long
    Dim nKekLen As Long
    
    abWK = cnvBytesFromHexStr("503D75C73630A7B02ECF51B9B29B907749310B77B0B2E054")
    abKek = cnvBytesFromHexStr("c17a44e8 e28d7d64 81d1ddd5 0a3b8914")
    nWkLen = UBound(abWK) + 1
    nKekLen = UBound(abKek) + 1
    
    nKdLen = CIPHER_KeyUnwrap(0, 0, abWK(0), nWkLen, abKek(0), nKekLen, PKI_BC_AES128)
    If nKdLen <= 0 Then
        Debug.Print " returns " & nKdLen & ": " & pkiErrorLookup(nKdLen)
        Exit Sub
    End If
    ReDim abKeyData(nKdLen - 1)
    nWkLen = CIPHER_KeyUnwrap(abKeyData(0), nKdLen, abWK(0), nWkLen, abKek(0), nKekLen, PKI_BC_AES128)
    Debug.Print "K=" & cnvHexStrFromBytes(abKeyData)

End Sub

Public Sub V_Test_CIPHER_KeyUnwrap2()
    Debug.Print "Testing CIPHER_KeyUnwrap vbacode ..."
    Dim lpWK() As Byte
    Dim lpKeyData() As Byte
    Dim lpKEK() As Byte
    
    lpKeyData = cnvBytesFromHexStr("00112233 44556677 8899aabb ccddeeff")
    lpKEK = cnvBytesFromHexStr("c17a44e8 e28d7d64 81d1ddd5 0a3b8914")
    ' NB Specific nonzero option required in nOptions
    lpWK = cipherKeyWrap(lpKeyData, lpKEK, PKI_BC_AES128)
    Debug.Print "WK=" & cnvHexStrFromBytes(lpWK)
    Debug.Print "OK=503D75C73630A7B02ECF51B9B29B907749310B77B0B2E054"
    
    ' Now unwrap the KEK
    Dim lpKeyUnwrapped() As Byte
    lpKeyUnwrapped = cipherKeyUnwrap(lpWK, lpKEK, PKI_BC_AES128)
    Debug.Print "KY=" & cnvHexStrFromBytes(lpKeyUnwrapped)
    Debug.Print "OK=00112233445566778899AABBCCDDEEFF"
End Sub

Public Sub V_Test_CMS_GetSigDataDigest()
    Debug.Print "Testing CMS_GetSigDataDigest code ..."
    Dim nDigAlg As Long
    Dim strCMSFile As String
    Dim strHexDigest As String
    strCMSFile = "DetSignByAlice.bin"
    strHexDigest = String(PKI_MAX_HASH_CHARS, " ")
    nDigAlg = CMS_GetSigDataDigest(strHexDigest, Len(strHexDigest), strCMSFile, "", 0)
    Debug.Print "CMS_GetSigDataDigest returns " & nDigAlg
    If nDigAlg < 0 Then
        Exit Sub
    End If
    Debug.Print "Extracted digest is"
    Debug.Print "[" & strHexDigest & "]"

End Sub

Public Sub V_Test_CMS_GetSigDataDigest2()
    Debug.Print "Testing CMS_GetSigDataDigest code ..."
    Dim strCMSFile As String
    Dim strHexDigest As String
    Dim nDigAlg As Long
    Dim strData As String
    Dim nDataLen As Long
    Dim strContentDigest As String
    Dim nHashLen As Long
    
    strCMSFile = "4.2.bin"
    
    ' 1. Get the digest value
    strHexDigest = String(PKI_MAX_HASH_CHARS, " ")
    nDigAlg = CMS_GetSigDataDigest(strHexDigest, _
        Len(strHexDigest), strCMSFile, "", 0)
    Debug.Print "CMS_GetSigDataDigest returns " & nDigAlg
    If nDigAlg < 0 Then
        Exit Sub
    End If
    Debug.Print "Extracted digest is"
    Debug.Print "[" & strHexDigest & "]"
    
    ' 2. Go get the content - in this case it's in the signed-data object
    nDataLen = CMS_ReadSigDataToString("", 0, strCMSFile, 0)
    If nDataLen <= 0 Then
        Exit Sub
    End If
    strData = String(nDataLen, " ")
    nDataLen = CMS_ReadSigDataToString(strData, nDataLen, strCMSFile, 0)
    Debug.Print "CMS_ReadSigDataToString returns " & nDataLen
    Debug.Print "Data is [" & strData & "]"
    
    ' 3. Compute independently the hash of what we found
    ' (Note how we use the digest algorithm code returned above)
    strContentDigest = String(PKI_MAX_HASH_CHARS, " ")
    nHashLen = HASH_HexFromString(strContentDigest, _
        Len(strContentDigest), strData, nDataLen, nDigAlg)
    Debug.Print "Computed hash of content is"
    Debug.Print "[" & strContentDigest & "]"
    
    ' 4. Can we match this hash digest with
    '    what we extracted from the signed-data?
    strContentDigest = Left(strContentDigest, nHashLen)
    strHexDigest = Left(strHexDigest, nHashLen)
    If strContentDigest = strHexDigest Then
        Debug.Print "SUCCESS - digests match!"
    Else
        Debug.Print "FAILS! - no match"
    End If

End Sub

Public Sub V_Test_CMS_GetSigDataDigest3()
    Debug.Print "Testing CMS_GetSigDataDigest vbacode ..."
    Dim strHexDigest As String
    Dim strData As String
    Const strCMSFile As String = "4.2.bin"
    
    ' Extract the digest value
    strHexDigest = cmsGetSigDataDigest(strCMSFile, "")
    Debug.Print "extracted digest=[" & strHexDigest & "]"
    ' Extract content from signed-data file
    strData = cmsReadSigDataToString(strCMSFile)
    Debug.Print "content='" & strData & "'"
    ' Compute digest value over the content
    Debug.Print "computed digest =[" & hashHexFromBytes(StrConv(strData, vbFromUnicode), PKI_HASH_SHA1) & "]"

End Sub

Public Sub V_Test_CMS_MakeComprData()
    Debug.Print "Testing CMS_MakeComprData code ..."
    Dim nRet As Long
    Dim strBaseFile As String
    Dim strCompFile As String
    Dim strChkFile As String
    Dim strFileType As String
    
    strBaseFile = "sonnets.txt"
    strCompFile = "sonnets.p7z"
    
    ' Create a CMS compressed-data file
    nRet = CMS_MakeComprData(strCompFile, strBaseFile, 0)
    Debug.Print "CMS_MakeComprData returns " & nRet & " (expecting 0)"
    Debug.Print "FileLen('" & strBaseFile & "')=" & FileLen(strBaseFile)
    Debug.Print "FileLen('" & strCompFile & "')=" & FileLen(strCompFile)
    
    ' Check ASN.1 file type
    strFileType = String(PKI_ASN1_TYPE_MAXCHARS, " ")
    nRet = ASN1_Type(strFileType, Len(strFileType), strCompFile, 0)
    Debug.Print "File Type='" & Left(strFileType, nRet) & "'"
    
    ' Now check we can read it
    strChkFile = "sonnets-uncompr.txt"
    nRet = CMS_ReadComprData(strChkFile, strCompFile, 0)
    Debug.Print "CMS_ReadComprData returns " & nRet & " (expecting +ve)"
    
    ' And check with no-inflate option
    strChkFile = "sonnets-noinflate.txt"
    nRet = CMS_ReadComprData(strChkFile, strCompFile, PKI_CMS_NO_INFLATE)
    Debug.Print "CMS_ReadComprData(PKI_CMS_NO_INFLATE) returns " & nRet & " (expecting +ve)"

End Sub

Public Sub V_Test_CMS_MakeDetachedSig()
    Debug.Print "Testing CMS_MakeDetachedSig code ..."
    Dim nRet As Long
    Dim strEPKFile As String
    Dim strCertFile As String
    Dim strOutFile As String
    Dim strHexDigest As String
    Dim strPrivateKey As String
    
    strEPKFile = "AlicePrivRSASign.p8e"
    strCertFile = "AliceRSASignByCarl.cer"
    strOutFile = "DetSignByAlice.bin"
    strHexDigest = "406aec085279ba6e16022d9e0629c0229687dd48"
    
    ' First, Alice reads her private key into a string
    strPrivateKey = rsaReadPrivateKey(strEPKFile, "password")
    If Len(strPrivateKey) = 0 Then
        MsgBox "Cannot read private key"
        Exit Sub
    End If
    
    ' Alice makes a detached signature using
    ' the hash of the content and her private key
    nRet = CMS_MakeDetachedSig(strOutFile, strHexDigest, _
        strCertFile, strPrivateKey, 0)
    Debug.Print "CMS_MakeDetachedSig returns " & nRet

End Sub

Public Sub V_Test_CMS_MakeEnvData()
    Debug.Print "Testing CMS_MakeEnvData code ..."
    Dim nRet As Long
    Dim strOutputFile As String
    Dim strInputFile As String
    Dim strCertFile As String
    
    strOutputFile = "cmsalice2bob.p7m"
    strInputFile = "excontent.txt"
    strCertFile = "BobRSASignByCarl.cer"
    ' This should return 1 (indicating one successful recipient)
    nRet = CMS_MakeEnvData(strOutputFile, strInputFile, strCertFile, "", 0, 0)
    Debug.Print "CMS_MakeEnvData returns " & nRet

End Sub

Public Sub V_Test_CMS_MakeEnvData2()
    Debug.Print "Testing CMS_MakeEnvData code ..."
    ' This should return 2 (indicating two successful recipients)
    nRet = CMS_MakeEnvData("cms2bobandcarl.p7m", "excontent.txt", _
        "BobRSASignByCarl.cer;CarlRSASelf.cer", "", 0, 0)
    Debug.Print "CMS_MakeEnvData returns " & nRet

End Sub

Public Sub V_Test_CMS_MakeEnvData3()
    Debug.Print "Testing CMS_MakeEnvData code ..."
    nRet = CMS_MakeEnvData("cms2bob_aes128.p7m", "excontent.txt", _
        "BobRSASignByCarl.cer", "", 0, PKI_BC_AES128)
    Debug.Print "CMS_MakeEnvData returns " & nRet

End Sub

Public Sub V_Test_CMS_MakeEnvData4()
    Debug.Print "Testing CMS_MakeEnvData code ..."
    Dim nRet As Long
    Dim strEnvDataFile As String
    Dim strInputFile As String
    Dim strCheckFile As String
    strEnvDataFile = "envbig.p7m"
    strInputFile = "bigfile.txt"
    Debug.Print "File " & strInputFile & "=" & FileLen(strInputFile) & " bytes"
    ' Make enveloped-data file: this should return 1 (indicating one successful recipient)
    nRet = CMS_MakeEnvData(strEnvDataFile, strInputFile, "bob.cer;", "", 0, PKI_CMS_BIGFILE)
    Debug.Print "CMS_MakeEnvData returns " & nRet & " (expected 1 => # recipients)"
    ' Now decrypt using Bob's private key
    Dim strPrivateKey As String
    strPrivateKey = rsaReadPrivateKey("bob.p8e", "password")
    strCheckFile = strEnvDataFile & ".out.txt"
    nRet = CMS_ReadEnvData(strCheckFile, strEnvDataFile, "", strPrivateKey, PKI_CMS_BIGFILE)
    Debug.Print "CMS_ReadEnvData returns " & nRet & " (expected 0 => success)"
    ' Check file length
    Debug.Print "File " & strCheckFile & "=" & FileLen(strCheckFile) & " bytes"

End Sub

Public Sub V_Test_CMS_MakeEnvData5()
    Debug.Print "Testing CMS_MakeEnvData vbacode ..."
    Dim n As Long
    ' Create an enveloped CMS object (ktri type) to Bob using Bob's RSA key...
    n = cmsMakeEnvData("cms2bob_aes128.p7m", "excontent.txt", "BobRSASignByCarl.cer", "", PKI_BC_AES128 Or PKI_KT_RSAES_OAEP)
    ' Same but using authenticated encryption and creating an authEnvelopedData object...
    n = cmsMakeEnvData("cms2bob_aes128auth.p7m", "excontent.txt", "BobRSASignByCarl.cer", "", PKI_AEAD_AES_128_GCM Or PKI_KT_RSAES_OAEP)
    ' Create an enveloped CMS object (kari type) to Dana using Dana's ECC key...
    n = cmsMakeEnvData("cms2dana_hkdf.p7m", "excontent.txt", "lamps-dana.encrypt.crt", "", PKI_BC_AES256 Or PKI_HASH_SHA256 Or PKI_KDF_HKDF Or PKI_KWRAP_AES256)
    ' Create an enveloped CMS object (kekri type) using a previously distributed symmetric key-encryption key (KEK)...
    n = cmsMakeEnvData("cms_envdata_kekri.p7m", "excontent.txt", "type=@kekri,keyid=ourcommonkey", "#x0123456789ABCDEFF0E1D2C3B4A59687", PKI_BC_AES256 Or PKI_HASH_SHA256 Or PKI_KWRAP_AES128)
    ' Create an enveloped CMS object (pwri type) using password-based key management...
    n = cmsMakeEnvData("cms_envdata_pwri.p7m", "excontent.txt", "type=@pwri", "password12345", PKI_BC_AES192)

End Sub

Public Sub V_Test_CMS_MakeEnvDataFromBytes()
    Debug.Print "Testing CMS_MakeEnvDataFromBytes code ..."
    Dim nRet As Long
    Dim strEnvDataFile As String
    Dim strData As String
    Dim abData() As Byte
    Dim nBytes As Long
    
    ' Input contains two non-ASCII characters:
    '   U+00CD Latin capital letter I with acute, encodes as (0x) C3 8D
    '   U+00F1 Latin small letter N with tilde, encodes as (0x) C3 B1
    strData = "<doc><name c='es'>&#205;ñigo</name></doc>"
    ' Convert Unicode string to UTF-8-encoded byte array
    nBytes = CNV_UTF8BytesFromLatin1(ByVal 0&, 0, strData)
    ReDim abData(nBytes - 1)
    nBytes = CNV_UTF8BytesFromLatin1(abData(0), nBytes, strData)
    Debug.Print "INPUT STR=""" & strData & """" & " (" & Len(strData) & " chars)"
    Debug.Print "HEX(UTF8)=" & cnvHexStrFromBytes(abData) & " (" & UBound(abData) + 1 & " bytes)"
    
    ' Create a CMS enveloped-data object using RSA-OAEP and AES-128 for content encryption
    strEnvDataFile = "cmsalice2bob_utf8.p7m"
    nRet = CMS_MakeEnvDataFromBytes(strEnvDataFile, _
        abData(0), nBytes, "BobRSASignByCarl.cer", "", 0, PKI_KT_RSAES_OAEP Or PKI_BC_AES128)
    ' This should return 1 (indicating one successful recipient)
    Debug.Print "CMS_MakeEnvDataFromBytes returns " & nRet & " (= # recipients)"
    Debug.Assert nRet > 0
    Debug.Print "Created enveloped-data file '" & strEnvDataFile & "'"

End Sub

Public Sub V_Test_CMS_MakeEnvDataFromString()
    Debug.Print "Testing CMS_MakeEnvDataFromString code ..."
    ' This should return 1 (indicating one successful recipient)
    nRet = CMS_MakeEnvDataFromString("cmsalice2bob1.p7m", _
        "This is some sample content.", "BobRSASignByCarl.cer", "", 0, 0)
    Debug.Print "CMS_MakeEnvDataFromString returns " & nRet

End Sub

Public Sub V_Test_CMS_MakeEnvDataFromString2()
    Debug.Print "Testing CMS_MakeEnvDataFromString vbacode ..."
    Dim strCertList As String
    Dim strCMSFile As String
    Dim nRet As Long
    Dim strQuery As String
    
    ' Use Dana's X22519 certificate
    strCMSFile = "dana_alice_hkdf.p7m"
    strCertList = "lamps-dana.encrypt.crt"
    ' Use AES256 for content encryption and Ephemeral-Static ECDH key agreement using HKDF key derivation function with SHA-256 and aes256-wrap
    nRet = cmsMakeEnvDataFromString(strCMSFile, "This is some sample content.", strCertList, "", PKI_BC_AES256 Or PKI_HASH_SHA256 Or PKI_KDF_HKDF Or PKI_KWRAP_AES256)
    Debug.Print "cmsMakeEnvDataFromString returns " & nRet & " (expecting 1)"
    ' Query EnvelopedData file
    Debug.Print "FILE: " & strCMSFile
    strQuery = "contentEncryptionAlgorithm"
    Debug.Print "QueryEnvData('" & strQuery & "')=" & cmsQueryEnvData(strCMSFile, strQuery)
    strQuery = "keyEncryptionAlgorithm"
    Debug.Print "QueryEnvData('" & strQuery & "')=" & cmsQueryEnvData(strCMSFile, strQuery)
    strQuery = "keyWrapAlgorithm"
    Debug.Print "QueryEnvData('" & strQuery & "')=" & cmsQueryEnvData(strCMSFile, strQuery)

End Sub

Public Sub V_Test_CMS_MakeSigData()
    Debug.Print "Testing CMS_MakeSigData code ..."
    Dim strPRIFile As String
    Dim strPrivateKey As String
    Dim nIntKeyLen As Long
    Dim nRet As Long
    Dim strInputFile As String
    Dim strOutputFile As String
    Dim strCertFile As String
    
    strPRIFile = "AlicePrivRSASign.pri"
    strCertFile = "AliceRSASignByCarl.cer"
    strInputFile = "excontent.txt"
    strOutputFile = "BasicSignByAlice.bin"
    
    ' First we need to read in the private key string
    ' NB: This version is not encrypted, so no password needed
    nIntKeyLen = RSA_ReadAnyPrivateKey("", 0, strPRIFile, "", 0)
    Debug.Print "nIntKeyLen = " & nIntKeyLen
    If nIntKeyLen <= 0 Then
        Debug.Print pkiGetLastError()
        MsgBox "Unable to retrieve private key"
        Exit Sub
    End If
    ' Pre-dimension the string to receive data
    strPrivateKey = String(nIntKeyLen, " ")
    ' Read in the Private Key
    nRet = RSA_ReadAnyPrivateKey(strPrivateKey, nIntKeyLen, strPRIFile, "", 0)
    Debug.Print "Key size=" & RSA_KeyBits(strPrivateKey) & " bits"
    
    ' Now we can sign our message
    nRet = CMS_MakeSigData(strOutputFile, strInputFile, strCertFile, strPrivateKey, 0)
    Debug.Print "CMS_MakeSigData returns " & nRet

End Sub

Public Sub V_Test_CMS_MakeSigData2()
    Debug.Print "Testing CMS_MakeSigData code ..."
    Dim nRet As Long
    Dim strOutputFile As String
    Dim strCertList As String
    
    ' Make a list of certs separated by semi-colons (;)
    strCertList = "CarlRSASelf.cer;" & "AliceRSASignByCarl.cer"
    Debug.Print "CertList=" & strCertList
    strOutputFile = "SigDataCertsOnly.p7c"
    
    ' Create a certs-only .p7c chain
    nRet = CMS_MakeSigData(strOutputFile, "", strCertList, "", PKI_CMS_CERTS_ONLY)
    Debug.Print "CMS_MakeSigData returns " & nRet
    If nRet <> 0 Then Debug.Print pkiGetLastError()

End Sub

Public Sub V_Test_CMS_MakeSigDataFromSigValue()
    Debug.Print "Testing CMS_MakeSigDataFromSigValue code ..."
    Dim strDataHex As String
    Dim strSigHex As String
    Dim abData() As Byte
    Dim abSigValue() As Byte
    Dim nSigLen As Long
    Dim nDataLen As Long
    Dim strCertFile As String
    Dim strCMSFile As String
    Dim nRet As Long
    
    ' Data to be signed in hex format:
    strDataHex = "54:68:69:73:20:69:73:20:73:6f:6d:65:20:73:61:6d" & _
        "70:6c:65:20:63:6f:6e:74:65:6e:74:2e"
    ' The signature (generated by the smart card) is:
    strSigHex = "2F:23:82:D2:F3:09:5F:B8:0C:58:EB:4E:9D:BF:89:9A" & _
        "81:E5:75:C4:91:3D:D3:D0:D5:7B:B6:D5:FE:94:A1:8A" & _
        "AC:E3:C4:84:F5:CD:60:4E:27:95:F6:CF:00:86:76:75" & _
        "3F:2B:F0:E7:D4:02:67:A7:F5:C7:8D:16:04:A5:B3:B5" & _
        "E7:D9:32:F0:24:EF:E7:20:44:D5:9F:07:C5:53:24:FA" & _
        "CE:01:1D:0F:17:13:A7:2A:95:9D:2B:E4:03:95:14:0B" & _
        "E9:39:0D:BA:CE:6E:9C:9E:0C:E8:98:E6:55:13:D4:68" & _
        "6F:D0:07:D7:A2:B1:62:4C:E3:8F:AF:FD:E0:D5:5D:C7"
    strCertFile = "AliceRSASignByCarl.cer"
    strCMSFile = "BasicSignByAliceExternal.bin"
    
    ' Convert the hex strings into byte arrays (non-hex chars are stripped)
    abData = cnvBytesFromHexStr(strDataHex)
    abSigValue = cnvBytesFromHexStr(strSigHex)
    ' Compute lengths
    nDataLen = UBound(abData) - LBound(abData) + 1
    nSigLen = UBound(abSigValue) - LBound(abSigValue) + 1
    
    ' Create the signed-data file
    nRet = CMS_MakeSigDataFromSigValue(strCMSFile, abSigValue(0), _
        nSigLen, abData(0), nDataLen, strCertFile, 0)
    Debug.Print "CMS_MakeSigDataFromSigValue returns " & nRet

End Sub

Public Sub V_Test_CMS_MakeSigDataFromBytes()
    Debug.Print "Testing CMS_MakeSigDataFromBytes code ..."
        Dim nRet As Long
        Dim strSigDataFile As String
        Dim strData As String
        Dim abData() As Byte
        Dim nBytes As Long
        Dim strPrivateKey As String
        
        ' Input contains two non-ASCII characters:
        '   U+00CD Latin capital letter I with acute, encodes as (0x) C3 8D
        '   U+00F1 Latin small letter N with tilde, encodes as (0x) C3 B1
        strData = "<doc><name c='es'>&#205;ñigo</name></doc>"
        ' Convert Unicode string to UTF-8-encoded byte array
        nBytes = CNV_UTF8BytesFromLatin1(ByVal 0&, 0, strData)
        ReDim abData(nBytes - 1)
        nBytes = CNV_UTF8BytesFromLatin1(abData(0), nBytes, strData)
        Debug.Print "INPUT STR=""" & strData & """" & " (" & Len(strData) & " chars)"
        Debug.Print "HEX(UTF8)=" & cnvHexStrFromBytes(abData) & " (" & UBound(abData) + 1 & " bytes)"
        
        '  We need Alice's private key
        strPrivateKey = rsaReadPrivateKey("AlicePrivRSASign.p8e", "password")
        If Len(strPrivateKey) = 0 Then
            MsgBox "Cannot read private key"
            Exit Sub
        End If
        
        ' Create a CMS signed-data object
        strSigDataFile = "basicsignedbyalice_utf8.p7m"
        nRet = CMS_MakeSigDataFromBytes(strSigDataFile, _
            abData(0), nBytes, "AliceRSASignByCarl.cer", strPrivateKey, PKI_SIG_RSA_PSS_SHA256)
        ' This should return 0 indicating success
        Debug.Print "CMS_MakeSigDataFromBytes returns " & nRet & " (expected 0)"
        Debug.Assert 0 = nRet
        Debug.Print "Created signed-data file '" & strSigDataFile & "'"
    
CleanUp:
        wipeString strPrivateKey

End Sub

Public Sub V_Test_CMS_MakeSigDataFromBytes2()
    Debug.Print "Testing CMS_MakeSigDataFromBytes vbacode ..."
    Dim strSigDataFile As String
    Dim strCertFile As String
    Dim lpData() As Byte
    Dim strPrivateKey As String
    Dim strQuery As String
    Dim r As Long
        
    ' Input contains two non-ASCII characters:
    '   U+00CD Latin capital letter I with acute, encodes as (0x) C3 8D
    '   U+00F1 Latin small letter N with tilde, encodes as (0x) C3 B1
    ' Convert Unicode string to UTF-8-encoded byte array to be signed
    lpData = cnvUTF8BytesFromLatin1("<doc><name c='es'>&#xCD;ñigo</name></doc>")
    Debug.Print "HEX(data to be signed)=" & cnvToHex(lpData)
    ' Read in Dana's ED25519 private key
    strPrivateKey = eccReadPrivateKey("lamps-dana.p8.pem", "")
    strCertFile = "lamps-dana.crt"
    
    ' Create a CMS signed-data object
    strSigDataFile = "signeddata-utf8-dana.p7m"
    r = cmsMakeSigDataFromBytes(strSigDataFile, lpData, strCertFile, strPrivateKey, PKI_SIG_ED25519 Or PKI_CMS_INCLUDE_ATTRS Or PKI_CMS_ADD_SIGNINGCERT)
    
    Debug.Print "cmsMakeSigDataFromBytes returns " & r & " (expected 0)"
    Debug.Assert 0 = r
    Debug.Print "FILE: " & strSigDataFile
    ' Query the signed-data object
    strQuery = "signatureAlgorithm"
    Debug.Print "QuerySigData('" & strQuery & "')=" & cmsQuerySigData(strSigDataFile, strQuery)
    strQuery = "signingCertHash"
    Debug.Print "QuerySigData('" & strQuery & "')=" & cmsQuerySigData(strSigDataFile, strQuery)
    ' Check thumbprint of cert, this should match the signingCertHash
    Debug.Print "CertThumb=" & x509CertThumb(strCertFile)
    ' Read back the signed data
    lpData = cmsReadSigDataToBytes(strSigDataFile)
    Debug.Print "HEX(recovered content)=" & cnvToHex(lpData)

End Sub

Public Sub V_Test_CMS_QueryEnvData()
    Debug.Print "Testing CMS_QueryEnvData vbacode ..."
    Dim strQuery As String
    Dim strOutput As String
    Dim strEnvDataFile As String
    
    strEnvDataFile = "5.1.bin"
    Debug.Print "FILE: " & strEnvDataFile
    strQuery = "keyEncryptionAlgorithm"
    strOutput = cmsQueryEnvData(strEnvDataFile, strQuery, 0)
    Debug.Print strQuery & " ==> " & strOutput
    strQuery = "contentEncryptionAlgorithm"
    strOutput = cmsQueryEnvData(strEnvDataFile, strQuery, 0)
    Debug.Print strQuery & " ==> " & strOutput
    strQuery = "sizeofEncryptedContent"
    strOutput = cmsQueryEnvData(strEnvDataFile, strQuery, 0)
    Debug.Print strQuery & " ==> " & strOutput

End Sub

Public Sub V_Test_CMS_QuerySigData()
    Debug.Print "Testing CMS_QuerySigData vbacode ..."
    Dim strCMSFile As String
    Dim strQuery As String
    Dim strOutput As String
    
    strCMSFile = "4.6.bin"
    Debug.Print "FILE: " & strCMSFile
    strQuery = "version"
    strOutput = cmsQuerySigData(strCMSFile, strQuery)
    Debug.Print strQuery & " ==> [" & strOutput & "]"
    strQuery = "digestAlgorithm"
    strOutput = cmsQuerySigData(strCMSFile, strQuery)
    Debug.Print strQuery & " ==> [" & strOutput & "]"
    
    strCMSFile = "4.7.bin"
    Debug.Print "FILE: " & strCMSFile
    strQuery = "version"
    strOutput = cmsQuerySigData(strCMSFile, strQuery)
    Debug.Print strQuery & " ==> [" & strOutput & "]"
    strQuery = "signatureAlgorithm"
    strOutput = cmsQuerySigData(strCMSFile, strQuery)
    Debug.Print strQuery & " ==> [" & strOutput & "]"
    
    strCMSFile = "BasicSignByAlice_attr.bin"
    Debug.Print "FILE: " & strCMSFile
    strQuery = "signingTime"
    strOutput = cmsQuerySigData(strCMSFile, strQuery)
    Debug.Print strQuery & " ==> [" & strOutput & "]"
End Sub

Public Sub V_Test_CMS_ReadEnvData()
    Debug.Print "Testing CMS_ReadEnvData code ..."
    Dim nRet As Long
    Dim strFileIn As String
    Dim strFileOut As String
    Dim strPrivateKey As String
    
    ' Bob reads his private key into a string
    strPrivateKey = rsaReadPrivateKey("BobPrivRSAEncrypt.p8e", "password")
    If Len(strPrivateKey) = 0 Then
        MsgBox "Cannot read private key"
        Exit Sub
    End If
    
    ' Decrypt the input file; send plaintext to new output file
    strFileIn = "cmsalice2bob.p7m"
    strFileOut = "fromalice.txt"
    nRet = CMS_ReadEnvData(strFileOut, strFileIn, "", strPrivateKey, 0)
    Debug.Print "CMS_ReadEnvData returns " & nRet
    
    ' Clean up
    WIPE_String strPrivateKey, Len(strPrivateKey)
    strPrivateKey = ""

End Sub

Public Sub V_Test_CMS_ReadEnvDataToBytes()
    Debug.Print "Testing CMS_ReadEnvDataToBytes code ..."
        Dim strEnvDataFile As String
        Dim strData As String
        Dim abData() As Byte
        Dim nBytes As Long
        Dim strPrivateKey As String
        Dim nChars As Long
        
        ' Read encrypted content from file
        strEnvDataFile = "cmsalice2bob_utf8.p7m"
        
        '  Read in Bob's encrypted private key
        strPrivateKey = rsaReadPrivateKey("BobPrivRSAEncrypt.p8e", "password")
        If Len(strPrivateKey) = 0 Then
            MsgBox "Cannot read private key"
            Exit Sub
        End If
    
        ' Find required length
        nBytes = CMS_ReadEnvDataToBytes(ByVal 0&, 0, strEnvDataFile, "", strPrivateKey, 0)
        Debug.Print "CMS_ReadEnvDataToBytes returns " & nBytes
        If nBytes <= 0 Then
            MsgBox "CMS_ReadEnvDataToBytes FAILED"
            GoTo CleanUp
        End If
        ' Dimension byte array to receive data
        ReDim abData(nBytes - 1)
        ' Extract the plaintext data
        nBytes = CMS_ReadEnvDataToBytes(abData(0), nBytes, strEnvDataFile, "", strPrivateKey, 0)
        Debug.Print "HEX(PT)=" & cnvHexStrFromBytes(abData)
        ' Convert from UTF-8 to VB Unicode string
        nChars = CNV_Latin1FromUTF8Bytes(0, 0, abData(0), nBytes)
         If nChars <= 0 Then
            MsgBox "CNV_Latin1FromUTF8Bytes FAILED"
            GoTo CleanUp
        End If
        strData = String(nChars, " ")
        nChars = CNV_Latin1FromUTF8Bytes(strData, nChars, abData(0), nBytes)
        Debug.Print "PT=" & strData
        
CleanUp:
        wipeString strPrivateKey

End Sub

Public Sub V_Test_CMS_ReadEnvDataToBytes2()
    Debug.Print "Testing CMS_ReadEnvDataToBytes vbacode ..."
    Dim strPrivateKey As String
    Dim lpData() As Byte
    Dim strData As String
    
    ' Read in private key to internal key string
    strPrivateKey = rsaReadPrivateKey("BobPrivRSAEncrypt.p8e", "password")
    Debug.Assert Len(strPrivateKey) > 0
    
    ' 1. Decrypted content is UTF-8 encoded
    lpData = cmsReadEnvDataToBytes("cmsalice2bob_utf8.p7m", "", strPrivateKey, 0)
    Debug.Assert cnvBytesLen(lpData) > 0
    Debug.Print "HEX(PT)=" & cnvHexStrFromBytes(lpData)
    ' Convert from UTF-8-encoded bytes to VB Unicode string
    strData = cnvLatin1FromUTF8Bytes(lpData)
    Debug.Print "PT=" & strData
    
    ' 2. Decrypted content is plain ANSI string
    strData = cmsReadEnvDataToString("cms2bobandcarl.p7m", "", strPrivateKey, 0)
    Debug.Print "PT=" & strData
    
    ' Clean up
    strPrivateKey = wipeString(strPrivateKey)

End Sub

Public Sub V_Test_CMS_ReadEnvDataToString()
    Debug.Print "Testing CMS_ReadEnvDataToString code ..."
        Dim strPrivateKey As String
        Dim strFileIn As String
        Dim strDataOut As String
        Dim nLen As Long
        Dim strCertFile As String
        
        strFileIn = "cms2bobandcarl.p7m"
        
        ' First, Bob reads his private key into a string
        strPrivateKey = rsaReadPrivateKey("BobPrivRSAEncrypt.p8e", "password")
        If Len(strPrivateKey) = 0 Then
            MsgBox "Cannot read private key"
            Exit Sub
        End If
        
        ' Query the size of encrypted content (no need for an output buffer)
        nLen = CMS_QueryEnvData("", 0, strFileIn, "sizeofEncryptedContent", 0)
        Debug.Print "CMS_QueryEnvData returns " & nLen
        
        If nLen <= 0 Then
            GoTo CleanUp
        End If
        
        ' Pre-dimension string and read in the plaintext
        ' The final plaintext will always be shorter than the encrypted content.
        strDataOut = String(nLen, " ")
        nLen = CMS_ReadEnvDataToString(strDataOut, nLen, _
            strFileIn, "", strPrivateKey, 0)
        Debug.Print "CMS_ReadEnvDataToString returns " & nLen
        If nLen > 0 Then
            ' Fix correct size for final, unpadded plaintext
            strDataOut = Left(strDataOut, nLen)
            Debug.Print "Plaintext is '" & strDataOut & "'"
        End If
        
CleanUp:
        WIPE_String strPrivateKey, Len(strPrivateKey)
        strPrivateKey = ""

End Sub

Public Sub V_Test_CMS_ReadEnvDataToString2()
    Debug.Print "Testing CMS_ReadEnvDataToString vbacode ..."
    Dim strPrivateKey As String
    Dim lpData() As Byte
    Dim strData As String
    
    ' Read in private key to internal key string
    strPrivateKey = rsaReadPrivateKey("BobPrivRSAEncrypt.p8e", "password")
    Debug.Assert Len(strPrivateKey) > 0
    
    ' 1. Decrypted content is UTF-8 encoded
    lpData = cmsReadEnvDataToBytes("cmsalice2bob_utf8.p7m", "", strPrivateKey, 0)
    Debug.Assert cnvBytesLen(lpData) > 0
    Debug.Print "HEX(PT)=" & cnvHexStrFromBytes(lpData)
    ' Convert from UTF-8-encoded bytes to VB Unicode string
    strData = cnvLatin1FromUTF8Bytes(lpData)
    Debug.Print "PT=" & strData
    
    ' 2. Decrypted content is plain ANSI string
    strData = cmsReadEnvDataToString("cms2bobandcarl.p7m", "", strPrivateKey, 0)
    Debug.Print "PT=" & strData
    
    ' Clean up
    strPrivateKey = wipeString(strPrivateKey)

End Sub

Public Sub V_Test_CMS_ReadSigData()
    Debug.Print "Testing CMS_ReadSigData code ..."
    Dim nRet As Long
    Dim strFileIn As String
    Dim strFileOut As String
    
    strFileIn = "BasicSignByAlice.bin"
    strFileOut = "BasicSignByAlice.dat"
    nRet = CMS_ReadSigData(strFileOut, strFileIn, 0)
    Debug.Print "CMS_ReadSigData returns " & nRet

End Sub

Public Sub V_Test_CMS_ReadSigDataToBytes()
    Debug.Print "Testing CMS_ReadSigDataToBytes code ..."
    Dim nRet As Long
    Dim strSigDataFile As String
    Dim abData() As Byte
    Dim nBytes As Long
    
    strSigDataFile = "basicsignedbyalice_utf8.p7m"
    Debug.Print "Reading signed-data file '" & strSigDataFile & "'"
    ' How long is the content to be read?
    nBytes = CMS_ReadSigDataToBytes(ByVal 0&, 0, strSigDataFile, 0)
    Debug.Print "CMS_ReadSigDataToBytes returns " & nBytes
    If nBytes <= 0 Then
        Exit Sub
    End If
    ' Dimension byte array to receive data
    ReDim abData(nBytes - 1)
    nBytes = CMS_ReadSigDataToBytes(abData(0), nBytes, strSigDataFile, 0)
    ' Display extracted content in hex
    Debug.Print "HEX(data)=" & cnvHexStrFromBytes(abData) & " (" & UBound(abData) + 1 & " bytes)"

End Sub

Public Sub V_Test_CMS_ReadSigDataToBytes2()
    Debug.Print "Testing CMS_ReadSigDataToBytes vbacode ..."
    Dim lpData() As Byte
    Dim strData As String
    
    ' Read UTF-8 encoded data from signed-data CMS object
    lpData = cmsReadSigDataToBytes("basicsignedbyalice_utf8.p7m")
    Debug.Assert cnvBytesLen(lpData) > 0
    Debug.Print "HEX(CONTENT)=" & cnvHexStrFromBytes(lpData)
    ' Convert from UTF-8-encoded bytes to VB Unicode string
    strData = cnvLatin1FromUTF8Bytes(lpData)
    Debug.Print "CONTENT='" & strData & "'"
End Sub

Public Sub V_Test_CMS_ReadSigDataToString()
    Debug.Print "Testing CMS_ReadSigDataToString code ..."
    Dim nRet As Long
    Dim strFileIn As String
    Dim strData As String
    Dim nDataLen As Long
    strFileIn = "4.2.bin"
    ' How long is the content to be read?
    nDataLen = CMS_ReadSigDataToString("", 0, strFileIn, 0)
    If nDataLen <= 0 Then
        Exit Sub
    End If
    ' Pre-dimension string to receive data
    strData = String(nDataLen, " ")
    nRet = CMS_ReadSigDataToString(strData, nDataLen, strFileIn, 0)
    Debug.Print "CMS_ReadSigDataToString returns " & nRet
    Debug.Print "Data is [" & strData & "]"

End Sub

Public Sub V_Test_CMS_ReadSigDataToString2()
    Debug.Print "Testing CMS_ReadSigDataToString vbacode ..."
    Dim strHexDigest As String
    Dim strData As String
    Const strCMSFile As String = "4.2.bin"
    
    ' Extract the digest value
    strHexDigest = cmsGetSigDataDigest(strCMSFile, "")
    Debug.Print "extracted digest=[" & strHexDigest & "]"
    ' Extract content from signed-data file
    strData = cmsReadSigDataToString(strCMSFile)
    Debug.Print "content='" & strData & "'"
    ' Compute digest value over the content
    Debug.Print "computed digest =[" & hashHexFromBytes(StrConv(strData, vbFromUnicode), PKI_HASH_SHA1) & "]"

End Sub

Public Sub V_Test_CMS_VerifySigData()
    Debug.Print "Testing CMS_VerifySigData code ..."
    Dim nRet As Long
    Dim strInputFile As String
    strInputFile = "BasicSignByAlice.bin"
    nRet = CMS_VerifySigData(strInputFile, "", "", 0)
    Debug.Print "CMS_VerifySigData returns " & nRet & " (expecting 0)"

End Sub

Public Sub V_Test_CNV_Base58FromBytes()
    Debug.Print "Testing CNV_Base58FromBytes code ..."
    Dim strBase58 As String
    Dim abData() As Byte
    Dim nBytes As Long
    Dim nChars As Long
    
    ' Create a byte array for testing
    abData = cnvBytesFromHexStr("00010966776006953D5567439E5E39F86A0D273BEED61967F6")
    nBytes = UBound(abData) + 1
    Debug.Print "INPUT: " & cnvHexStrFromBytes(abData)
    
    ' Encode bytes as base58 string
    ' Find length of output string
    nChars = CNV_Base58FromBytes("", 0, abData(0), nBytes)
    If nChars < 0 Then Exit Sub ' ERROR
    ' Dimension string to receive output
    strBase58 = String(nChars, " ")
    ' Create output string
    nChars = CNV_Base58FromBytes(strBase58, nChars, abData(0), nBytes)
    
    Debug.Print "OUTPUT: " & strBase58

End Sub

Public Sub V_Test_CNV_Base58FromBytes2()
    Debug.Print "Testing CNV_Base58FromBytes vbacode ..."
    Dim lpData() As Byte
    Dim strBase58 As String
    
    lpData = cnvBytesFromHexStr("00010966776006953D5567439E5E39F86A0D273BEED61967F6")
    strBase58 = cnvBase58FromBytes(lpData)
    Debug.Print strBase58
    ' Decode base58 string to byte array
    lpData = cnvBase58ToBytes(strBase58)
    Debug.Print cnvHexStrFromBytes(lpData)
    strBase58 = "DiManagement"
    Debug.Print "INPUT: " & strBase58
    lpData = cnvBase58ToBytes(strBase58)
    Debug.Print cnvHexStrFromBytes(lpData)
       
End Sub

Public Sub V_Test_CNV_Base58ToBytes()
    Debug.Print "Testing CNV_Base58ToBytes code ..."
    Dim strBase58 As String
    Dim abData() As Byte
    Dim nBytes As Long
    
    ' Decode base58 string to byte array
    strBase58 = "16UwLL9Risc3QfPqBUvKofHmBQ7wMtjvM"
    Debug.Print "INPUT: " & strBase58
    nBytes = CNV_Base58ToBytes(0, 0, strBase58)
    If nBytes < 0 Then Exit Sub ' ERROR
    ReDim abData(nBytes - 1)
    nBytes = CNV_Base58ToBytes(abData(0), nBytes, strBase58)
    ' Display byte array in hex
    Debug.Print "OUTPUT=" & cnvHexStrFromBytes(abData)
    
    ' Again (plug!)
    strBase58 = "DiManagement"
    Debug.Print "INPUT: " & strBase58
    nBytes = CNV_Base58ToBytes(0, 0, strBase58)
    If nBytes < 0 Then Exit Sub ' ERROR
    ReDim abData(nBytes - 1)
    nBytes = CNV_Base58ToBytes(abData(0), nBytes, strBase58)
    ' Display byte array in hex
    Debug.Print "OUTPUT=" & cnvHexStrFromBytes(abData)

End Sub

Public Sub V_Test_CNV_Base58ToBytes2()
    Debug.Print "Testing CNV_Base58ToBytes vbacode ..."
    Dim lpData() As Byte
    Dim strBase58 As String
    
    lpData = cnvBytesFromHexStr("00010966776006953D5567439E5E39F86A0D273BEED61967F6")
    strBase58 = cnvBase58FromBytes(lpData)
    Debug.Print strBase58
    ' Decode base58 string to byte array
    lpData = cnvBase58ToBytes(strBase58)
    Debug.Print cnvHexStrFromBytes(lpData)
    strBase58 = "DiManagement"
    Debug.Print "INPUT: " & strBase58
    lpData = cnvBase58ToBytes(strBase58)
    Debug.Print cnvHexStrFromBytes(lpData)
       
End Sub

Public Sub V_Test_CNV_ByteEncoding()
    Debug.Print "Testing CNV_ByteEncoding code ..."
    Dim abLatin1() As Byte
    Dim abUTF8() As Byte
    Dim nLatBytes As Long
    Dim nUtfBytes As Long
    ' Set up a byte array with the following 4 characters encoded in Latin-1
    '  U+0061 LATIN SMALL LETTER A
    '  U+00E9 LATIN SMALL LETTER E WITH ACUTE
    '  U+00F1 LATIN SMALL LETTER N WITH TILDE
    '  U+0062 LATIN SMALL LETTER B
    nLatBytes = 4
    ReDim abLatin1(nLatBytes - 1)  ' NB required size minus 1
    abLatin1(0) = Asc("a")
    abLatin1(1) = &HE9
    abLatin1(2) = &HF1
    abLatin1(3) = Asc("b")
    ' Display in hex format
    Debug.Print "Latin-1=" & cnvHexStrFromBytes(abLatin1) & " (" & nLatBytes & " bytes)"
    ' Convert encoding to UTF-8
    ' First find new length and pre-dimension array
    nUtfBytes = CNV_ByteEncoding(0, 0, abLatin1(0), nLatBytes, PKI_CNV_UTF8_FROM_LATIN1)
    If nUtfBytes <= 0 Then Exit Sub 'ERROR
    ReDim abUTF8(nUtfBytes - 1)
    nUtfBytes = CNV_ByteEncoding(abUTF8(0), nUtfBytes, abLatin1(0), nLatBytes, PKI_CNV_UTF8_FROM_LATIN1)
    ' Display in hex format
    Debug.Print "UTF-8  =" & cnvHexStrFromBytes(abUTF8) & " (" & nUtfBytes & " bytes)"

End Sub

Public Sub V_Test_CNV_ByteEncoding2()
    Debug.Print "Testing CNV_ByteEncoding vbacode ..."
    Dim lpLatin1() As Byte
    Dim lpUTF8() As Byte
    ' Set up a byte array with the following 4 characters encoded in Latin-1
    '  U+0061 LATIN SMALL LETTER A
    '  U+00E9 LATIN SMALL LETTER E WITH ACUTE
    '  U+00F1 LATIN SMALL LETTER N WITH TILDE
    '  U+0062 LATIN SMALL LETTER B
    lpLatin1 = cnvBytesFromHexStr("61E9F162")
    Debug.Print "Latin-1=" & cnvHexStrFromBytes(lpLatin1) & " (" & cnvBytesLen(lpLatin1) & " bytes)"
    lpUTF8 = cnvByteEncoding(lpLatin1, PKI_CNV_UTF8_FROM_LATIN1)
    Debug.Print "UTF-8  =" & cnvHexStrFromBytes(lpUTF8) & " (" & cnvBytesLen(lpUTF8) & " bytes)"
    ' And back again the other way...
    lpLatin1 = cnvByteEncoding(lpUTF8, PKI_CNV_LATIN1_FROM_UTF8)
    Debug.Print "Latin-1=" & cnvHexStrFromBytes(lpLatin1) & " (" & cnvBytesLen(lpLatin1) & " bytes)"
End Sub

Public Sub V_Test_CNV_CheckUTF8Bytes()
    Debug.Print "Testing CNV_CheckUTF8Bytes vbacode ..."
    Dim strData As String
    Dim lpDataUTF8() As Byte
    strData = "abcóé&#205;áñ"
    Debug.Print "Latin-1 string='" & strData & "'"
    Debug.Print " (" & Len(strData) & " characters)"
    lpDataUTF8 = cnvUTF8BytesFromLatin1(strData)
    Debug.Print "UTF-8=(0x)" & cnvHexStrFromBytes(lpDataUTF8)
    Debug.Print " (" & cnvBytesLen(lpDataUTF8) & " bytes)"
    Debug.Print "cnvCheckUTF8Bytes returns " & cnvCheckUTF8Bytes(lpDataUTF8) & " (expected 2)"
    ' And back to a string
    Dim strLatin1 As String
    strLatin1 = cnvLatin1FromUTF8Bytes(lpDataUTF8)
    Debug.Print "Back to string='" & strLatin1 & "'"
End Sub

Public Sub V_Test_CNV_CheckUTF8File()
    Debug.Print "Testing CNV_CheckUTF8File code ..."
    Dim strFileName As String
    Dim nRet As Long
    
    strFileName = "test-utf8.xml"
    nRet = CNV_CheckUTF8File(strFileName)
    Debug.Print "CNV_CheckUTF8File(" & strFileName & ") returns " & nRet
    strFileName = "test-iso88591.xml"
    nRet = CNV_CheckUTF8File(strFileName)
    Debug.Print "CNV_CheckUTF8File(" & strFileName & ") returns " & nRet

End Sub

Public Sub V_Test_CNV_Latin1FromUTF8Bytes()
    Debug.Print "Testing CNV_Latin1FromUTF8Bytes vbacode ..."
    Dim strData As String
    Dim lpDataUTF8() As Byte
    strData = "abcóé&#205;áñ"
    Debug.Print "Latin-1 string='" & strData & "'"
    Debug.Print " (" & Len(strData) & " characters)"
    lpDataUTF8 = cnvUTF8BytesFromLatin1(strData)
    Debug.Print "UTF-8=(0x)" & cnvHexStrFromBytes(lpDataUTF8)
    Debug.Print " (" & cnvBytesLen(lpDataUTF8) & " bytes)"
    Debug.Print "cnvCheckUTF8Bytes returns " & cnvCheckUTF8Bytes(lpDataUTF8) & " (expected 2)"
    ' And back to a string
    Dim strLatin1 As String
    strLatin1 = cnvLatin1FromUTF8Bytes(lpDataUTF8)
    Debug.Print "Back to string='" & strLatin1 & "'"

End Sub

Public Sub V_Test_CNV_Latin1FromUTF8Bytes2()
    Debug.Print "Testing CNV_Latin1FromUTF8Bytes vbacode ..."
    Dim strPrivateKey As String
    Dim lpData() As Byte
    Dim strData As String
    
    ' Read in private key to internal key string
    strPrivateKey = rsaReadPrivateKey("BobPrivRSAEncrypt.p8e", "password")
    Debug.Assert Len(strPrivateKey) > 0
    
    ' 1. Decrypted content is UTF-8 encoded
    lpData = cmsReadEnvDataToBytes("cmsalice2bob_utf8.p7m", "", strPrivateKey, 0)
    Debug.Assert cnvBytesLen(lpData) > 0
    Debug.Print "HEX(PT)=" & cnvHexStrFromBytes(lpData)
    ' Convert from UTF-8-encoded bytes to VB Unicode string
    strData = cnvLatin1FromUTF8Bytes(lpData)
    Debug.Print "PT=" & strData
    
    ' 2. Decrypted content is plain ANSI string
    strData = cmsReadEnvDataToString("cms2bobandcarl.p7m", "", strPrivateKey, 0)
    Debug.Print "PT=" & strData
    
    ' Clean up
    strPrivateKey = wipeString(strPrivateKey)
    

End Sub

Public Sub V_Test_CNV_Latin1FromUTF8Bytes3()
    Debug.Print "Testing CNV_Latin1FromUTF8Bytes vbacode ..."
    Dim lpData() As Byte
    Dim strData As String
    
    ' Read UTF-8 encoded data from signed-data CMS object
    lpData = cmsReadSigDataToBytes("basicsignedbyalice_utf8.p7m")
    Debug.Assert cnvBytesLen(lpData) > 0
    Debug.Print "HEX(CONTENT)=" & cnvHexStrFromBytes(lpData)
    ' Convert from UTF-8-encoded bytes to VB Unicode string
    strData = cnvLatin1FromUTF8Bytes(lpData)
    Debug.Print "CONTENT='" & strData & "'"
End Sub

Public Sub V_Test_CNV_NumFromBytes()
    Debug.Print "Testing CNV_NumFromBytes code ..."
    Dim abData() As Byte
    Dim nBytes As Long
    Dim nRet As Long
    
    abData = cnvBytesFromHexStr("DEADBEEF")
    nBytes = UBound(abData) + 1
    Debug.Print "INPUT:  " & cnvHexStrFromBytes(abData)
    ' Default big-endian order
    nRet = CNV_NumFromBytes(abData(0), nBytes, 0)
    Debug.Print "CNV_NumFromBytes(BE)=0x" & Hex(nRet)
    ' Little-endian order
    nRet = CNV_NumFromBytes(abData(0), nBytes, PKI_CNV_LITTLE_ENDIAN)
    Debug.Print "CNV_NumFromBytes(LE)=0x" & Hex(nRet)
    ' Input shorter than 4 bytes is padded on the right with zeros
    nRet = CNV_NumFromBytes(abData(0), 3, PKI_CNV_BIG_ENDIAN)
    Debug.Print "CNV_NumFromBytes(BE)=0x" & Hex(nRet)
    nRet = CNV_NumFromBytes(abData(0), 3, PKI_CNV_LITTLE_ENDIAN)
    Debug.Print "CNV_NumFromBytes(LE)=0x" & Hex(nRet)

End Sub

Public Sub V_Test_CNV_NumToBytes()
    Debug.Print "Testing CNV_NumToBytes code ..."
    Dim abData() As Byte
    Dim nBytes As Long
    Dim nNumber As Long
    Dim nRet As Long
    
    nBytes = 4
    ReDim abData(nBytes - 1)
    nNumber = &HDEADBEEF
    Debug.Print "INPUT=0x" & Hex(nNumber) & " (" & nNumber & ")"
    ' Default big-endian order
    nRet = CNV_NumToBytes(abData(0), nBytes, nNumber, 0)
    Debug.Print "CNV_NumToBytes(BE)=" & cnvHexStrFromBytes(abData)
    ' Little-endian order
    nRet = CNV_NumToBytes(abData(0), nBytes, nNumber, PKI_CNV_LITTLE_ENDIAN)
    Debug.Print "CNV_NumToBytes(LE)=" & cnvHexStrFromBytes(abData)

End Sub

Public Sub V_Test_CNV_NumToBytes2()
    Debug.Print "Testing CNV_NumToBytes vbacode ..."
    Dim lpData() As Byte
    Dim nBytes As Long
    Dim nNumber As Long
    
    nNumber = &HDEADBEEF
    Debug.Print "INPUT=0x" & Hex(nNumber) & " (" & nNumber & ")"
    ' Default big-endian order
    lpData = cnvNumToBytes(nNumber)
    Debug.Print "cnvNumToBytes(BE)=" & cnvHexStrFromBytes(lpData)
    ' Little-endian order
    lpData = cnvNumToBytes(nNumber, PKI_CNV_LITTLE_ENDIAN)
    Debug.Print "cnvNumToBytes(LE)=" & cnvHexStrFromBytes(lpData)

End Sub

Public Sub V_Test_CNV_ReverseBytes()
    Debug.Print "Testing CNV_ReverseBytes code ..."
     Dim abData() As Byte
     Dim nBytes As Long
     Dim nRet As Long
     
     abData = cnvBytesFromHexStr("DEADBEEF01")
     nBytes = UBound(abData) + 1
     Debug.Print "INPUT:  " & cnvHexStrFromBytes(abData)
     nRet = CNV_ReverseBytes(abData(0), abData(0), nBytes)
     Debug.Print "OUTPUT: " & cnvHexStrFromBytes(abData)

End Sub

Public Sub V_Test_CNV_UTF8BytesFromLatin1()
    Debug.Print "Testing CNV_UTF8BytesFromLatin1 code ..."
    Dim strData As String
    Dim abDataUTF8() As Byte
    Dim nRet As Long
    Dim nBytes As Long
    Dim nChars As Long
    Dim strNew As String
    
    ' Our original string data contains 5 non-ASCII characters
    strData = "abcóé&#205;áñ"
    Debug.Print "Latin-1 string='" & strData & "'"
    Debug.Print " (" & Len(strData) & " characters)"
    
    ' Convert directly to array of bytes in UTF-8 encoding
    ' Find required length first
    nBytes = CNV_UTF8BytesFromLatin1(0, 0, strData)
    If nBytes <= 0 Then
        Debug.Print "Failed to convert to UTF-8: " & nBytes
        Exit Sub
    End If
    ' Pre-dimension
    ReDim abDataUTF8(nBytes - 1)
    nBytes = CNV_UTF8BytesFromLatin1(abDataUTF8(0), nBytes, strData)
    ' Display in hex
    Debug.Print "UTF-8=(0x)" & cnvHexStrFromBytes(abDataUTF8)
    Debug.Print " (" & nBytes & " bytes)"
    
    ' Check if this is valid UTF-8 encoding
    nRet = CNV_CheckUTF8Bytes(abDataUTF8(0), nBytes)
    Debug.Print "CNV_CheckUTF8Bytes returns " & nRet & " (expected 2)"
    
    ' Now put back into a string
    nChars = CNV_Latin1FromUTF8Bytes("", 0, abDataUTF8(0), nBytes)
    If nChars <= 0 Then
        Debug.Print "Failed to convert to string: " & nChars
        Exit Sub
    End If
    strNew = String(nChars, " ")
    nChars = CNV_Latin1FromUTF8Bytes(strNew, nChars, abDataUTF8(0), nBytes)
    Debug.Print "New string='" & strNew & "' (" & nChars & " characters)"

End Sub

Public Sub V_Test_CNV_UTF8BytesFromLatin12()
    Debug.Print "Testing CNV_UTF8BytesFromLatin1 vbacode ..."
    Dim strData As String
    Dim lpDataUTF8() As Byte
    strData = "abcóé&#205;áñ"
    Debug.Print "Latin-1 string='" & strData & "'"
    Debug.Print " (" & Len(strData) & " characters)"
    lpDataUTF8 = cnvUTF8BytesFromLatin1(strData)
    Debug.Print "UTF-8=(0x)" & cnvHexStrFromBytes(lpDataUTF8)
    Debug.Print " (" & cnvBytesLen(lpDataUTF8) & " bytes)"
    Debug.Print "cnvCheckUTF8Bytes returns " & cnvCheckUTF8Bytes(lpDataUTF8) & " (expected 2)"
    ' And back to a string
    Dim strLatin1 As String
    strLatin1 = cnvLatin1FromUTF8Bytes(lpDataUTF8)
    Debug.Print "Back to string='" & strLatin1 & "'"

End Sub

Public Sub V_Test_CNV_UTF8BytesFromLatin13()
    Debug.Print "Testing CNV_UTF8BytesFromLatin1 vbacode ..."
    Dim strData As String
    Dim strDigest As String
    ' Our original string data
    strData = "Estándares de Electrónica de México para mañana"
    ' Compute SHA-1 hash over UTF-8 encoded byte array
    strDigest = hashHexFromBytes(cnvUTF8BytesFromLatin1(strData), PKI_HASH_SHA1)
    Debug.Print "Digest=" & strDigest
End Sub

Public Sub V_Test_COMPR_Compress()
    Debug.Print "Testing COMPR_Compress code ..."
    Dim strPlain As String
    Dim strBack As String
    Dim abPlain() As Byte
    Dim abCompressed() As Byte
    Dim nCompLen As Long
    Dim nUncompLen As Long
    Dim nRet As Long
    
    ' COMPRESSSION (deflation)
    
    ' Set the plaintext message
    strPlain = "hello, hello, hello. This is a 'hello world' message " & _
        "for the world, repeat, for the world."
    ' Convert to an array of bytes
    abPlain = StrConv(strPlain, vbFromUnicode)
    nUncompLen = UBound(abPlain) + 1
    ' Find required compressed length by calling with zero length value
    nCompLen = COMPR_Compress(0, 0, abPlain(0), nUncompLen, 0)
    ReDim abCompressed(nCompLen - 1)
    ' Now compress plaintext
    Call COMPR_Compress(abCompressed(0), nCompLen, abPlain(0), nUncompLen, 0)
    Debug.Print "Compressed " & nUncompLen & " bytes to " & nCompLen
    
    ' DECOMPRESSSION (inflation)
    
    ' Uncompress the compressed data
    ' Find the required length of uncompressed data
    nUncompLen = COMPR_Uncompress(0, 0, abCompressed(0), nCompLen, 0)
    Debug.Print "Required uncompressed length is " & nUncompLen & " bytes"
    ReDim abPlain(nUncompLen - 1)
    nRet = COMPR_Uncompress(abPlain(0), nUncompLen, abCompressed(0), nCompLen, 0)
    
    ' Convert back to a string
    strBack = StrConv(abPlain, vbUnicode)
    Debug.Print strBack

End Sub

Public Sub V_Test_COMPR_Compress2()
    Debug.Print "Testing COMPR_Compress vbacode ..."
    Dim strPlain As String
    Dim lpToCompress() As Byte
    Dim lpCompressed() As Byte
    Dim lpUncompressed() As Byte
    strPlain = "hello, hello, hello. This is a 'hello world' message " & _
        "for the world, repeat, for the world."
    lpToCompress = StrConv(strPlain, vbFromUnicode)
    lpCompressed = comprCompress(lpToCompress)
    Debug.Print "OK=        " & "789CCB48CDC9C9D751C840A2F4144232328B15802851411D2CA2509E5F9493A2AE909B5A5C9C989EAA90965FA45092910A11D651284A2D484D2CD14115D6030086D11F4E"
    Debug.Print "COMPRESSED=" & cnvHexStrFromBytes(lpCompressed)
    lpUncompressed = comprUncompress(lpCompressed)
    Debug.Print "'" & StrConv(lpUncompressed, vbUnicode); "'"

End Sub

Public Sub V_Test_COMPR_Uncompress()
    Debug.Print "Testing COMPR_Uncompress vbacode ..."
    Dim strPlain As String
    Dim lpToCompress() As Byte
    Dim lpCompressed() As Byte
    Dim lpUncompressed() As Byte
    strPlain = "hello, hello, hello. This is a 'hello world' message " & _
        "for the world, repeat, for the world."
    lpToCompress = StrConv(strPlain, vbFromUnicode)
    lpCompressed = comprCompress(lpToCompress)
    Debug.Print "OK=        " & "789CCB48CDC9C9D751C840A2F4144232328B15802851411D2CA2509E5F9493A2AE909B5A5C9C989EAA90965FA45092910A11D651284A2D484D2CD14115D6030086D11F4E"
    Debug.Print "COMPRESSED=" & cnvHexStrFromBytes(lpCompressed)
    lpUncompressed = comprUncompress(lpCompressed)
    Debug.Print "'" & StrConv(lpUncompressed, vbUnicode); "'"

End Sub

Public Sub V_Test_ECC_DHSharedSecret()
    Debug.Print "Testing ECC_DHSharedSecret code ..."
    Dim strOurPriKeyHex As String
    Dim strTheirPubKeyHex As String
    Dim strOurPrivateKey As String
    Dim strTheirPublicKey As String
    Dim strCurveName As String
    Dim strCorrectHex As String
    Dim lpZZ() As Byte
    Dim nChars As Long
    Dim nBytes As Long
    Dim nBits As Long
    
    ' Ref: CAVS 14.1 ECC CDH Primitive (SP800 - 56A Section 5.7.1.2)
    ' Test Information for "testecccdh" ecccdhtestvectors.zip
    
    '[P-256]
    
    strCurveName = "P-256"
    ' Our private key is dUIT:
    strOurPriKeyHex = "7d7dc5f71eb29ddaf80d6214632eeae03d9058af1fb6d22ed80badb62bc1a534"
    ' Their public key as hex is "04" || QCAVSx || QCAVSy
    strTheirPubKeyHex = "04" & "700c48f77f56584c5cc632ca65640db91b6bacce3a4df6b42ce7cc838833d287" _
        + "db71e509e3fd9b060ddb20ba5c51dcc5948d46fbf640dfe0441782cab85fa4ac"
    ' Correct result is ZIUT
    strCorrectHex = "46fc62106420ff012e54a434fbdd2d25ccc5852060561e68040dd7778997bd7b"
    
    Debug.Print "Test for curve " & strCurveName & " ..."
    ' Read in keys to internal key strings
    ' Our private key...
    nChars = ECC_ReadKeyByCurve("", 0, strOurPriKeyHex, strCurveName, 0)
    Debug.Assert nChars > 0
    strOurPrivateKey = String(nChars, " ")
    nChars = ECC_ReadKeyByCurve(strOurPrivateKey, nChars, strOurPriKeyHex, strCurveName, 0)
    Debug.Assert nChars > 0
    ' Check the key we read in
    nBits = ECC_QueryKey("", 0, strOurPrivateKey, "keyBits", 0)
    Debug.Print "Our private key has " & nBits & " bits"
    
    ' Their public key...
    nChars = ECC_ReadKeyByCurve("", 0, strTheirPubKeyHex, strCurveName, 0)
    Debug.Assert nChars > 0
    strTheirPublicKey = String(nChars, " ")
    nChars = ECC_ReadKeyByCurve(strTheirPublicKey, nChars, strTheirPubKeyHex, strCurveName, 0)
    Debug.Assert nChars > 0
    ' Check the key we read in
    nBits = ECC_QueryKey("", 0, strTheirPublicKey, "keyBits", 0)
    Debug.Print "Their public key has " & nBits & " bits"
    
    ' Compute shared secret
    ' - find required length
    nBytes = ECC_DHSharedSecret(ByVal 0&, 0, strOurPrivateKey, strTheirPublicKey, 0)
    Debug.Print "ECC_DHSharedSecret returns " & nBytes & " (expecting +ve)"
    Debug.Assert nBytes > 0
    ' - allocate memory
    ReDim lpZZ(nBytes - 1)
    ' - do the business
    nBytes = ECC_DHSharedSecret(lpZZ(0), nBytes, strOurPrivateKey, strTheirPublicKey, 0)
    Debug.Assert nBytes > 0
    
    Debug.Print "ZZ=" & cnvHexStrFromBytes(lpZZ)
    ' Check the result
    Debug.Print "OK=" & strCorrectHex
    Debug.Assert UCase(cnvHexStrFromBytes(lpZZ)) = UCase(strCorrectHex)

End Sub

Public Sub V_Test_ECC_DHSharedSecret2()
    Debug.Print "Testing ECC_DHSharedSecret vbacode ..."
    Dim strCurveName As String
    Dim ourPrivateKey As String
    Dim theirPublicKey As String
    Dim lpZZ() As Byte
    
    ' Ref: RFC7748 Section 6.1
    Const alicePrivateKeyHex As String = "77076d0a7318a57d3c16c17251b26645df4c2f87ebc0992ab177fba51db92c2a"
    Const alicePublicKeyHex As String = "8520f0098930a754748b7ddcb43ef75a0dbf3a0d26381af4eba4a98eaa9b4e6a"
    Const bobPrivateKeyHex As String = "5dab087e624a8a4b79e17f8b83800ee66f3bb1292618b6fd1c2f8b27ff88e0eb"
    Const bobPublicKeyHex As String = "de9edb7d7b7dc1b4d35b61c2ece435373f8343c85b78674dadfc7e146f882b4f"
    
    strCurveName = "X25519"
    ' 1. Alice's private + Bob's public
    ourPrivateKey = eccReadKeyByCurve(alicePrivateKeyHex, strCurveName, PKI_ECC_PRIVATE_KEY)
    Debug.Print "Our key has " & eccQueryKey(ourPrivateKey, "keyBits") & " bits and is a " & _
        IIf(eccQueryKey(ourPrivateKey, "isPrivate") = "1", "Private", "Public") & " key"
    theirPublicKey = eccReadKeyByCurve(bobPublicKeyHex, strCurveName, PKI_ECC_PUBLIC_KEY)
    Debug.Print "Their key has " & eccQueryKey(theirPublicKey, "keyBits") & " bits and is a " & _
        IIf(eccQueryKey(theirPublicKey, "isPrivate") = "1", "Private", "Public") & " key"
    ' Compute shared secret
    lpZZ = eccDHSharedSecret(ourPrivateKey, theirPublicKey)
    Debug.Print "ZZ=" & cnvHexStrFromBytes(lpZZ)
    Debug.Print "OK=4a5d9d5ba4ce2de1728e3bf480350f25e07e21c947d19e3376f09b3c1e161742"
    
    ' 2. Bob's private + Alice's public
    ourPrivateKey = eccReadKeyByCurve(bobPrivateKeyHex, strCurveName, PKI_ECC_PRIVATE_KEY)
    Debug.Print "Our key has " & eccQueryKey(ourPrivateKey, "keyBits") & " bits and is a " & _
        IIf(eccQueryKey(ourPrivateKey, "isPrivate") = "1", "Private", "Public") & " key"
    theirPublicKey = eccReadKeyByCurve(alicePublicKeyHex, strCurveName, PKI_ECC_PUBLIC_KEY)
    Debug.Print "Their key has " & eccQueryKey(theirPublicKey, "keyBits") & " bits and is a " & _
        IIf(eccQueryKey(theirPublicKey, "isPrivate") = "1", "Private", "Public") & " key"
    ' Compute shared secret
    lpZZ = eccDHSharedSecret(ourPrivateKey, theirPublicKey)
    Debug.Print "ZZ=" & cnvHexStrFromBytes(lpZZ)
    Debug.Print "OK=4a5d9d5ba4ce2de1728e3bf480350f25e07e21c947d19e3376f09b3c1e161742"
End Sub

Public Sub V_Test_ECC_KeyHashCode()
    Debug.Print "Testing ECC_KeyHashCode code ..."
    Dim nRet As Long
    Dim nChars As Long
    Dim strPubKeyFile As String
    Dim strPriKeyFile As String
    Dim strIntKey As String
    Dim strPassword As String
    
    strPubKeyFile = "CA_ECC_P256.pub"
    strPriKeyFile = "CA_ECC_P256.p8e"
    strPassword = "password"
    
    ' 1. Read in private key to internal key string
    Debug.Print "FILE: " & strPriKeyFile
    ' Find required length of internal key string
    nChars = ECC_ReadPrivateKey("", 0, strPriKeyFile, strPassword, 0)
    Debug.Print "ECC_ReadPrivateKey returns " & nChars & " (expected +ve)"
    ' Dimension the string to receive output
    strIntKey = String(nChars, " ")
    ' Read it in
    nChars = ECC_ReadPrivateKey(strIntKey, Len(strIntKey), strPriKeyFile, strPassword, 0)
    ' Note: internal key string is only valid for the current session
    ' But the Key Hash Code is always the same
    nRet = ECC_KeyHashCode(strIntKey)
    Debug.Print "KeyHashCodePrivate=0x" & Hex(nRet)
    
    ' 2. Read in public key to internal string
    Debug.Print "FILE: " & strPubKeyFile
    ' Find required length of internal key string
    nChars = ECC_ReadPublicKey("", 0, strPubKeyFile, 0)
    Debug.Print "ECC_ReadPublicKey returns " & nChars & " (expected +ve)"
    ' Dimension the string to receive output
    strIntKey = String(nChars, " ")
    ' Read it in
    nChars = ECC_ReadPublicKey(strIntKey, Len(strIntKey), strPubKeyFile, 0)
    ' The public and private Key Hash Codes should match
    nRet = ECC_KeyHashCode(strIntKey)
    Debug.Print "KeyHashCodePublic=0x" & Hex(nRet)

End Sub

Public Sub V_Test_ECC_PublicKeyFromPrivate()
    Debug.Print "Testing ECC_PublicKeyFromPrivate code ..."
    Dim nRet As Long
    Dim nChars As Long
    Dim strIntPriKey As String
    Dim strIntPubKey As String
    Dim strKeyFile As String
    Dim strNewKeyFile As String
    Dim strPassword As String
    Dim strTypeName As String
    Dim strFileName As String
    
    strKeyFile = "myeckeyp521.p8"
    strPassword = "password"
    
    ' 1. READ IN THE PRIVATE KEY: int_string <- file
    Debug.Print "FILE: " & strKeyFile
    ' Find required length of internal key string
    nChars = ECC_ReadPrivateKey("", 0, strKeyFile, strPassword, 0)
    Debug.Print "ECC_ReadPrivateKey returns " & nChars & " (expected +ve)"
    If (nChars <= 0) Then Exit Sub   ' CATCH ERROR HERE
    ' Dimension the string to receive output
    strIntPriKey = String(nChars, " ")
    ' Read into internal key string
    nChars = ECC_ReadPrivateKey(strIntPriKey, Len(strIntPriKey), strKeyFile, strPassword, 0)
    Debug.Print "[" & strIntPriKey & "]"
    
    ' 2. CONVERT TO PUBLIC: int_string <-- int_string
    nChars = ECC_PublicKeyFromPrivate("", 0, strIntPriKey, 0)
    Debug.Print "ECC_PublicKeyFromPrivate returns " & nChars & " (expected +ve)"
    If (nChars <= 0) Then Exit Sub   ' CATCH ERROR HERE
    strIntPubKey = String(nChars, " ")
    nChars = ECC_PublicKeyFromPrivate(strIntPubKey, Len(strIntPubKey), strIntPriKey, 0)
    Debug.Print "[" & strIntPubKey & "]"
          
    ' 3. SAVE AS NEW PUBLIC KEY FILE: file <-- int_string
    strNewKeyFile = "myeckeyp521_new.pub"
    nRet = ECC_SaveKey(strNewKeyFile, strIntPubKey, 0)
    Debug.Print "ECC_SaveKey returns " & nRet & " (expected 0)"
    
    ' Check the type of file we made
    strTypeName = String(PKI_ASN1_TYPE_MAXCHARS, " ")
    strFileName = strNewKeyFile
    nChars = ASN1_Type(strTypeName, Len(strTypeName), strFileName, 0)
    If nChars > 0 Then Debug.Print strFileName & ": " & Left(strTypeName, nChars)

End Sub

Public Sub V_Test_ECC_PublicKeyFromPrivate2()
    Debug.Print "Testing ECC_PublicKeyFromPrivate vbacode ..."
    Dim strIntKey As String
    
    ' Read in public key from file
    strIntKey = eccReadPublicKey("myeckeyp256.pub")
    Debug.Assert Len(strIntKey) > 0
    Debug.Print "Key curve=" & eccQueryKey(strIntKey, "curveName", 0) & " keyBits=" & _
        eccQueryKey(strIntKey, "keyBits", 0) & _
        " and is a " & _
        IIf(eccQueryKey(strIntKey, "isPrivate") = "1", "Private", "Public") & " key"
    Debug.Print eccQueryKey(strIntKey, "publicKey")
    Debug.Print "KeyHashCode=0x" & Hex(ECC_KeyHashCode(strIntKey))
    
    ' Read in private key from file
    strIntKey = eccReadPrivateKey("myeckeyp256.p8", "password")
    Debug.Assert Len(strIntKey) > 0
    Debug.Print "Key curve=" & eccQueryKey(strIntKey, "curveName", 0) & " keyBits=" & _
        eccQueryKey(strIntKey, "keyBits", 0) & _
        " and is a " & _
        IIf(eccQueryKey(strIntKey, "isPrivate") = "1", "Private", "Public") & " key"
    Debug.Print eccQueryKey(strIntKey, "publicKey")
    Debug.Print "KeyHashCode=0x" & Hex(ECC_KeyHashCode(strIntKey))
    
    ' Derive public key from private key
    strIntKey = eccPublicKeyFromPrivate(strIntKey)
    Debug.Assert Len(strIntKey) > 0
    Debug.Print "Key curve=" & eccQueryKey(strIntKey, "curveName", 0) & " keyBits=" & _
        eccQueryKey(strIntKey, "keyBits", 0) & _
        " and is a " & _
        IIf(eccQueryKey(strIntKey, "isPrivate") = "1", "Private", "Public") & " key"
    Debug.Print eccQueryKey(strIntKey, "publicKey")
    Debug.Print "KeyHashCode=0x" & Hex(ECC_KeyHashCode(strIntKey))
End Sub

Public Sub V_Test_ECC_QueryKey()
    Debug.Print "Testing ECC_QueryKey code ..."
    Dim nRet As Long
    Dim nChars As Long
    Dim strIntKey As String
    Dim strKeyFile As String
    Dim strQuery As String
    Dim strBuffer As String
    Dim strPassword As String
    
    strKeyFile = "myeckeyp256.p8"
    strPassword = "password"
    
    Debug.Print "FILE: " & strKeyFile
    ' Find required length of internal key string
    nChars = ECC_ReadPrivateKey("", 0, strKeyFile, strPassword, 0)
    Debug.Print "ECC_ReadPrivateKey returns " & nChars & " (expected +ve)"
    ' Dimension the string to receive output
    strIntKey = String(nChars, " ")
    ' Read into an ephemeral internal key string
    nChars = ECC_ReadPrivateKey(strIntKey, Len(strIntKey), strKeyFile, strPassword, 0)
    ' Find the curve name (output as a string)
    strBuffer = String(32, " ")
    strQuery = "curveName"
    nChars = ECC_QueryKey(strBuffer, Len(strBuffer), strIntKey, strQuery, 0)
    If nChars > 0 Then Debug.Print "ECC_QueryKey('" & strQuery & "')=[" & Left(strBuffer, nChars) & "]"
    ' Find the key size in bits (NB returned directly)
    strQuery = "keyBits"
    nRet = ECC_QueryKey("", 0, strIntKey, strQuery, 0)
    Debug.Print "ECC_QueryKey('" & strQuery & "')=" & nRet & " (expected +ve)"
    ' Is it a private or public key?
    strQuery = "isPrivate"
    nRet = ECC_QueryKey("", 0, strIntKey, strQuery, 0)
    Debug.Print "ECC_QueryKey('" & strQuery & "')=" & nRet & " (expected 1 = True)"
    ' Extract the private key in hex form
    strQuery = "privateKey"
    ' Get required length of output string
    nChars = ECC_QueryKey("", 0, strIntKey, strQuery, 0)
    strBuffer = String(nChars, " ")
    nChars = ECC_QueryKey(strBuffer, Len(strBuffer), strIntKey, strQuery, 0)
    Debug.Print "ECC_QueryKey('" & strQuery & "')="
    If nChars > 0 Then Debug.Print "[" & Left(strBuffer, nChars) & "]"
    ' Extract the public key in hex form
    strQuery = "publicKey"
    nChars = ECC_QueryKey("", 0, strIntKey, strQuery, 0)
    strBuffer = String(nChars, " ")
    nChars = ECC_QueryKey(strBuffer, Len(strBuffer), strIntKey, strQuery, 0)
    Debug.Print "ECC_QueryKey('" & strQuery & "')="
    If nChars > 0 Then Debug.Print "[" & Left(strBuffer, nChars) & "]"

End Sub

Public Sub V_Test_ECC_QueryKey2()
    Debug.Print "Testing ECC_QueryKey vbacode ..."
    Dim curveName As String
    Dim alicePrivateKeyHex As String
    Dim ourPrivateKey As String
    
    curveName = "X25519"
    alicePrivateKeyHex = "77076d0a7318a57d3c16c17251b26645df4c2f87ebc0992ab177fba51db92c2a"
    
    ourPrivateKey = eccReadKeyByCurve(alicePrivateKeyHex, curveName, PKI_ECC_PRIVATE_KEY)
    Debug.Assert Len(ourPrivateKey) > 0
    Debug.Print "Key curve=" & eccQueryKey(ourPrivateKey, "curveName", 0) & " keyBits=" & eccQueryKey(ourPrivateKey, "keyBits", 0)

End Sub

Public Sub V_Test_ECC_ReadKeyByCurve()
    Debug.Print "Testing ECC_ReadKeyByCurve code ..."
    Dim nRet As Long
    Dim nChars As Long
    Dim strIntKey As String
    Dim strHexKey As String
    Dim strCurveName As String
    Dim strQuery As String
    Dim strBuffer As String
    Dim strBase58 As String
    Dim abTemp() As Byte
    Dim nBytes As Long
      
    ' 1. A NIST P-192 public key in X9.63 uncompressed format
    strHexKey = _
     "0496C248BE456192FA1380CCF615D171452F41FF31B92BA733524FD77168DEA4425A3EA8FD79B98DC7AFE83C86DCC39A96"
    strCurveName = "prime192v1"  ' A synonym for "P-192"
    Debug.Print "KEYHEX: " & strHexKey
    Debug.Print "CURVE: " & strCurveName
    ' Find required length of internal key string
    nChars = ECC_ReadKeyByCurve("", 0, strHexKey, strCurveName, 0)
    Debug.Print "ECC_ReadKeyByCurve returns " & nChars & " (expected +ve)"
    ' Dimension the string to receive output
    strIntKey = String(nChars, " ")
    ' Read into internal key string
    nChars = ECC_ReadKeyByCurve(strIntKey, Len(strIntKey), strHexKey, strCurveName, 0)
    ' Find the key size in bits
    strQuery = "keyBits"
    nRet = ECC_QueryKey("", 0, strIntKey, strQuery, 0)
    Debug.Print "ECC_QueryKey('" & strQuery & "')=" & nRet & " (expected +ve)"
    ' Is it a private or public key?
    strQuery = "isPrivate"
    nRet = ECC_QueryKey("", 0, strIntKey, strQuery, 0)
    Debug.Print "ECC_QueryKey('" & strQuery & "')=" & nRet & " (expected 0)"
    Debug.Print
    
    ' 2. A Bitcoin private key in base58 form
    strBase58 = "6ACCbmy9qwiFcuVgvxNNwMPfoghobzznWrLs3v7t3RmN"
    Debug.Print "KEYB58: " & strBase58
    strCurveName = "secp256k1"
    ' Convert to a hex string
    nBytes = CNV_Base58ToBytes(0, 0, strBase58)
    Debug.Assert (nBytes > 0)
    ReDim abTemp(nBytes - 1)
    nBytes = CNV_Base58ToBytes(abTemp(0), nBytes, strBase58)
    strHexKey = cnvHexStrFromBytes(abTemp)
    Debug.Print "KEYHEX: " & strHexKey
    Debug.Print "CURVE: " & strCurveName
    ' Find required length of internal key string
    nChars = ECC_ReadKeyByCurve("", 0, strHexKey, strCurveName, 0)
    Debug.Print "ECC_ReadKeyByCurve returns " & nChars & " (expected +ve)"
    ' Dimension the string to receive output
    strIntKey = String(nChars, " ")
    ' Read into internal key string
    nChars = ECC_ReadKeyByCurve(strIntKey, Len(strIntKey), strHexKey, strCurveName, 0)
    ' Find the key size in bits
    strQuery = "keyBits"
    nRet = ECC_QueryKey("", 0, strIntKey, strQuery, 0)
    Debug.Print "ECC_QueryKey('" & strQuery & "')=" & nRet & " (expected +ve)"
    ' Is it a private or public key?
    strQuery = "isPrivate"
    nRet = ECC_QueryKey("", 0, strIntKey, strQuery, 0)
    Debug.Print "ECC_QueryKey('" & strQuery & "')=" & nRet & " (expected 1)"
    
    ' Extract the public key in hex form
    strQuery = "publicKey"
    nChars = ECC_QueryKey("", 0, strIntKey, strQuery, 0)
    strBuffer = String(nChars, " ")
    nChars = ECC_QueryKey(strBuffer, Len(strBuffer), strIntKey, strQuery, 0)
    Debug.Print "ECC_QueryKey('" & strQuery & "')="
    If nChars > 0 Then Debug.Print "[" & Left(strBuffer, nChars) & "]"

End Sub

Public Sub V_Test_ECC_ReadKeyByCurve2()
    Debug.Print "Testing ECC_ReadKeyByCurve vbacode ..."
    Dim curveName As String
    Dim alicePrivateKeyHex As String
    Dim ourPrivateKey As String
    Dim nChars As Long
    
    curveName = "X25519"
    alicePrivateKeyHex = "77076d0a7318a57d3c16c17251b26645df4c2f87ebc0992ab177fba51db92c2a"
    
    ' The old long way...
    nChars = ECC_ReadKeyByCurve(vbNullString, 0, alicePrivateKeyHex, curveName, PKI_ECC_PRIVATE_KEY)
    Debug.Assert nChars > 0
    ourPrivateKey = String(nChars, " ")
    nChars = ECC_ReadKeyByCurve(ourPrivateKey, nChars, alicePrivateKeyHex, curveName, PKI_ECC_PRIVATE_KEY)
    
    ' The new short way with a wrapper function
    ourPrivateKey = eccReadKeyByCurve(alicePrivateKeyHex, curveName, PKI_ECC_PRIVATE_KEY)
    Debug.Assert Len(ourPrivateKey) > 0
    Debug.Print "Key curve=" & eccQueryKey(ourPrivateKey, "curveName", 0) & " keyBits=" & eccQueryKey(ourPrivateKey, "keyBits", 0)

End Sub

Public Sub V_Test_ECC_ReadKeyByCurve3()
    Debug.Print "Testing ECC_ReadKeyByCurve vbacode ..."
    Dim strCurveName As String
    Dim ourPrivateKey As String
    Dim theirPublicKey As String
    Dim lpZZ() As Byte
    
    ' Ref: RFC7748 Section 6.1
    Const alicePrivateKeyHex As String = "77076d0a7318a57d3c16c17251b26645df4c2f87ebc0992ab177fba51db92c2a"
    Const alicePublicKeyHex As String = "8520f0098930a754748b7ddcb43ef75a0dbf3a0d26381af4eba4a98eaa9b4e6a"
    Const bobPrivateKeyHex As String = "5dab087e624a8a4b79e17f8b83800ee66f3bb1292618b6fd1c2f8b27ff88e0eb"
    Const bobPublicKeyHex As String = "de9edb7d7b7dc1b4d35b61c2ece435373f8343c85b78674dadfc7e146f882b4f"
    
    strCurveName = "X25519"
    ' 1. Alice's private + Bob's public
    ourPrivateKey = eccReadKeyByCurve(alicePrivateKeyHex, strCurveName, PKI_ECC_PRIVATE_KEY)
    Debug.Print "Our key has " & eccQueryKey(ourPrivateKey, "keyBits") & " bits and is a " & _
        IIf(eccQueryKey(ourPrivateKey, "isPrivate") = "1", "Private", "Public") & " key"
    theirPublicKey = eccReadKeyByCurve(bobPublicKeyHex, strCurveName, PKI_ECC_PUBLIC_KEY)
    Debug.Print "Their key has " & eccQueryKey(theirPublicKey, "keyBits") & " bits and is a " & _
        IIf(eccQueryKey(theirPublicKey, "isPrivate") = "1", "Private", "Public") & " key"
    ' Compute shared secret
    lpZZ = eccDHSharedSecret(ourPrivateKey, theirPublicKey)
    Debug.Print "ZZ=" & cnvHexStrFromBytes(lpZZ)
    Debug.Print "OK=4a5d9d5ba4ce2de1728e3bf480350f25e07e21c947d19e3376f09b3c1e161742"
    
    ' 2. Bob's private + Alice's public
    ourPrivateKey = eccReadKeyByCurve(bobPrivateKeyHex, strCurveName, PKI_ECC_PRIVATE_KEY)
    Debug.Print "Our key has " & eccQueryKey(ourPrivateKey, "keyBits") & " bits and is a " & _
        IIf(eccQueryKey(ourPrivateKey, "isPrivate") = "1", "Private", "Public") & " key"
    theirPublicKey = eccReadKeyByCurve(alicePublicKeyHex, strCurveName, PKI_ECC_PUBLIC_KEY)
    Debug.Print "Their key has " & eccQueryKey(theirPublicKey, "keyBits") & " bits and is a " & _
        IIf(eccQueryKey(theirPublicKey, "isPrivate") = "1", "Private", "Public") & " key"
    ' Compute shared secret
    lpZZ = eccDHSharedSecret(ourPrivateKey, theirPublicKey)
    Debug.Print "ZZ=" & cnvHexStrFromBytes(lpZZ)
    Debug.Print "OK=4a5d9d5ba4ce2de1728e3bf480350f25e07e21c947d19e3376f09b3c1e161742"
End Sub

Public Sub V_Test_ECC_ReadPrivateKey()
    Debug.Print "Testing ECC_ReadPrivateKey code ..."
    Dim nRet As Long
    Dim nChars As Long
    Dim strIntKey As String
    Dim strKeyFile As String
    Dim strPassword As String
    Dim strNewKeyFile As String
    Dim strTypeName As String
    Dim strFileName As String
    
    strKeyFile = "myeckeyp256.p8"
    strPassword = "password"
    
    ' Find required length of internal key string
    nChars = ECC_ReadPrivateKey("", 0, strKeyFile, strPassword, 0)
    Debug.Print "ECC_ReadPrivateKey returns " & nChars & " (expected +ve)"
    ' Dimension the string to receive output
    strIntKey = String(nChars, " ")
    ' Read it in
    nChars = ECC_ReadPrivateKey(strIntKey, Len(strIntKey), strKeyFile, strPassword, 0)
    ' Caution: internal key string is only valid for the current session
    Debug.Print "[" & strIntKey & "]"
    
    ' Now save in a different format: ECPrivatekey in PEM encoding
    strNewKeyFile = "myeckey.pem"
    nRet = ECC_SaveKey(strNewKeyFile, strIntKey, PKI_KEY_FORMAT_PEM)
    Debug.Print "ECC_SaveKey returns " & nRet & " (expected 0)"
    
    ' Check the types of file we made
    strTypeName = String(PKI_ASN1_TYPE_MAXCHARS, " ")
    strFileName = strNewKeyFile
    nChars = ASN1_Type(strTypeName, Len(strTypeName), strFileName, 0)
    If nChars > 0 Then Debug.Print strFileName & ": " & Left(strTypeName, nChars)

End Sub

Public Sub V_Test_ECC_ReadPrivateKey2()
    Debug.Print "Testing ECC_ReadPrivateKey vbacode ..."
    Dim strIntKey As String
    
    ' Read in public key from file
    strIntKey = eccReadPublicKey("myeckeyp256.pub")
    Debug.Assert Len(strIntKey) > 0
    Debug.Print "Key curve=" & eccQueryKey(strIntKey, "curveName", 0) & " keyBits=" & _
        eccQueryKey(strIntKey, "keyBits", 0) & _
        " and is a " & _
        IIf(eccQueryKey(strIntKey, "isPrivate") = "1", "Private", "Public") & " key"
    Debug.Print eccQueryKey(strIntKey, "publicKey")
    Debug.Print "KeyHashCode=0x" & Hex(ECC_KeyHashCode(strIntKey))
    
    ' Read in private key from file
    strIntKey = eccReadPrivateKey("myeckeyp256.p8", "password")
    Debug.Assert Len(strIntKey) > 0
    Debug.Print "Key curve=" & eccQueryKey(strIntKey, "curveName", 0) & " keyBits=" & _
        eccQueryKey(strIntKey, "keyBits", 0) & _
        " and is a " & _
        IIf(eccQueryKey(strIntKey, "isPrivate") = "1", "Private", "Public") & " key"
    Debug.Print eccQueryKey(strIntKey, "publicKey")
    Debug.Print "KeyHashCode=0x" & Hex(ECC_KeyHashCode(strIntKey))
    
    ' Derive public key from private key
    strIntKey = eccPublicKeyFromPrivate(strIntKey)
    Debug.Assert Len(strIntKey) > 0
    Debug.Print "Key curve=" & eccQueryKey(strIntKey, "curveName", 0) & " keyBits=" & _
        eccQueryKey(strIntKey, "keyBits", 0) & _
        " and is a " & _
        IIf(eccQueryKey(strIntKey, "isPrivate") = "1", "Private", "Public") & " key"
    Debug.Print eccQueryKey(strIntKey, "publicKey")
    Debug.Print "KeyHashCode=0x" & Hex(ECC_KeyHashCode(strIntKey))
End Sub

Public Sub V_Test_ECC_ReadPublicKey()
    Debug.Print "Testing ECC_ReadPublicKey code ..."
    Dim nRet As Long
    Dim nChars As Long
    Dim strIntKey As String
    Dim strKeyFile As String
    Dim strQuery As String
    
    strKeyFile = "myeckeyp521.pub"
    
    Debug.Print "FILE: " & strKeyFile
    ' Find required length of internal key string
    nChars = ECC_ReadPublicKey("", 0, strKeyFile, 0)
    Debug.Print "ECC_ReadPublicKey returns " & nChars & " (expected +ve)"
    ' Dimension the string to receive output
    strIntKey = String(nChars, " ")
    ' Read into internal key string
    nChars = ECC_ReadPublicKey(strIntKey, Len(strIntKey), strKeyFile, 0)
    Debug.Print "[" & strIntKey & "]"
    ' Find the key size in bits (NB returned directly)
    strQuery = "keyBits"
    nRet = ECC_QueryKey("", 0, strIntKey, strQuery, 0)
    Debug.Print "ECC_QueryKey('" & strQuery & "')=" & nRet & " (expected +ve)"
    ' Is it a private or public key?
    strQuery = "isPrivate"
    nRet = ECC_QueryKey("", 0, strIntKey, strQuery, 0)
    Debug.Print "ECC_QueryKey('" & strQuery & "')=" & nRet & " (expected 0)"

End Sub

Public Sub V_Test_ECC_ReadPublicKey2()
    Debug.Print "Testing ECC_ReadPublicKey vbacode ..."
    Dim strIntKey As String
    
    ' Read in public key from file
    strIntKey = eccReadPublicKey("myeckeyp256.pub")
    Debug.Assert Len(strIntKey) > 0
    Debug.Print "Key curve=" & eccQueryKey(strIntKey, "curveName", 0) & " keyBits=" & _
        eccQueryKey(strIntKey, "keyBits", 0) & _
        " and is a " & _
        IIf(eccQueryKey(strIntKey, "isPrivate") = "1", "Private", "Public") & " key"
    Debug.Print eccQueryKey(strIntKey, "publicKey")
    Debug.Print "KeyHashCode=0x" & Hex(ECC_KeyHashCode(strIntKey))
    
    ' Read in private key from file
    strIntKey = eccReadPrivateKey("myeckeyp256.p8", "password")
    Debug.Assert Len(strIntKey) > 0
    Debug.Print "Key curve=" & eccQueryKey(strIntKey, "curveName", 0) & " keyBits=" & _
        eccQueryKey(strIntKey, "keyBits", 0) & _
        " and is a " & _
        IIf(eccQueryKey(strIntKey, "isPrivate") = "1", "Private", "Public") & " key"
    Debug.Print eccQueryKey(strIntKey, "publicKey")
    Debug.Print "KeyHashCode=0x" & Hex(ECC_KeyHashCode(strIntKey))
    
    ' Derive public key from private key
    strIntKey = eccPublicKeyFromPrivate(strIntKey)
    Debug.Assert Len(strIntKey) > 0
    Debug.Print "Key curve=" & eccQueryKey(strIntKey, "curveName", 0) & " keyBits=" & _
        eccQueryKey(strIntKey, "keyBits", 0) & _
        " and is a " & _
        IIf(eccQueryKey(strIntKey, "isPrivate") = "1", "Private", "Public") & " key"
    Debug.Print eccQueryKey(strIntKey, "publicKey")
    Debug.Print "KeyHashCode=0x" & Hex(ECC_KeyHashCode(strIntKey))
End Sub

Public Sub V_Test_ECC_SaveEncKey()
    Debug.Print "Testing ECC_SaveEncKey code ..."
    Dim nRet As Long
    Dim nChars As Long
    Dim strIntKey As String
    Dim strPriKeyFile As String
    Dim strPassword As String
    Dim strNewKeyFile As String
    Dim strTypeName As String
    Dim strFileName As String
    
    strPriKeyFile = "myeckeyp256.p8"
    strPassword = "password"
    
    ' Find required length of internal key string
    nChars = ECC_ReadPrivateKey("", 0, strPriKeyFile, strPassword, 0)
    Debug.Print "ECC_ReadPrivateKey returns " & nChars & " (expected +ve)"
    ' Dimension the string to receive output
    strIntKey = String(nChars, " ")
    ' Read it in
    nChars = ECC_ReadPrivateKey(strIntKey, Len(strIntKey), strPriKeyFile, strPassword, 0)
    Debug.Print "[" & strIntKey & "]"
    
    ' Now save in a different format: ECPrivatekey
    strNewKeyFile = "myeckey.key"
    nRet = ECC_SaveKey(strNewKeyFile, strIntKey, 0)
    Debug.Print "ECC_SaveKey returns " & nRet & " (expected 0)"
    
    ' Check the types of file we made
    strTypeName = String(PKI_ASN1_TYPE_MAXCHARS, " ")
    strFileName = strNewKeyFile
    nChars = ASN1_Type(strTypeName, Len(strTypeName), strFileName, 0)
    If nChars > 0 Then Debug.Print strFileName & ": " & Left(strTypeName, nChars)

End Sub

Public Sub V_Test_ECC_SaveKey()
    Debug.Print "Testing ECC_SaveKey code ..."
    Dim nRet As Long
    Dim nChars As Long
    Dim strIntKey As String
    Dim strKeyFile As String
    Dim strPassword As String
    Dim strNewKeyFile As String
    Dim strTypeName As String
    Dim strFileName As String
    
    strKeyFile = "myeckeyp256.p8"
    strPassword = "password"
    
    Debug.Print "FILE: " & strKeyFile
    ' Find required length of internal key string
    nChars = ECC_ReadPrivateKey("", 0, strKeyFile, strPassword, 0)
    Debug.Print "ECC_ReadPrivateKey returns " & nChars & " (expected +ve)"
    ' Dimension the string to receive output
    strIntKey = String(nChars, " ")
    ' Read it in
    nChars = ECC_ReadPrivateKey(strIntKey, Len(strIntKey), strKeyFile, strPassword, 0)
    ' Caution: internal key string is only valid for the current session
    Debug.Print "[" & strIntKey & "]"
    
    ' Now save in a different format: ECPrivatekey in PEM encoding
    strNewKeyFile = "myeckey.pem"
    nRet = ECC_SaveKey(strNewKeyFile, strIntKey, PKI_KEY_FORMAT_PEM)
    Debug.Print "ECC_SaveKey returns " & nRet & " (expected 0)"
    
    ' Check the type of file we made
    strTypeName = String(PKI_ASN1_TYPE_MAXCHARS, " ")
    strFileName = strNewKeyFile
    nChars = ASN1_Type(strTypeName, Len(strTypeName), strFileName, 0)
    If nChars > 0 Then Debug.Print strFileName & ": " & Left(strTypeName, nChars)

End Sub

Public Sub V_Test_HASH_Bytes()
    Debug.Print "Testing HASH_Bytes code ..."
        Dim nRet As Long
        Dim abDigest() As Byte
        Dim abMessage() As Byte
        Dim nMsgLen As Long
        ' Set up message to be hashed
        abMessage = StrConv("abc", vbFromUnicode)
        nMsgLen = UBound(abMessage) + 1
        ' Pre-dimension digest array (NB zero-based so subtract one)
        ReDim abDigest(PKI_MAX_HASH_BYTES - 1)
        ' Create default hash (SHA1)
        nRet = HASH_Bytes(abDigest(0), PKI_MAX_HASH_BYTES, abMessage(0), nMsgLen, 0)
        If nRet > 0 Then ReDim Preserve abDigest(nRet - 1)
        Debug.Print nRet, cnvHexStrFromBytes(abDigest)
        
        ' Repeat for MD5
        ReDim abDigest(PKI_MAX_HASH_BYTES - 1)
        nRet = HASH_Bytes(abDigest(0), PKI_MAX_HASH_BYTES, abMessage(0), nMsgLen, PKI_HASH_MD5)
        If nRet > 0 Then ReDim Preserve abDigest(nRet - 1)
        Debug.Print nRet, cnvHexStrFromBytes(abDigest)

End Sub

Public Sub V_Test_HASH_Bytes2()
    Debug.Print "Testing HASH_Bytes vbacode ..."
    Dim strDigest As String
    Dim lpMessage() As Byte
    Dim lpDigest() As Byte
    
    ' Hex <-- Hex
    strDigest = hashHexFromHex("616263", PKI_HASH_SHA256)   ' "abc" in hex
    Debug.Print strDigest
    lpMessage = StrConv("abc", vbFromUnicode)   ' "abc" in a byte array
    ' Hex <-- Bytes
    strDigest = hashHexFromBytes(lpMessage, PKI_HASH_SHA256)
    Debug.Print strDigest
    ' Bytes <-- Bytes
    lpDigest = hashBytes(lpMessage, PKI_HASH_SHA256)
    Debug.Print cnvHexStrFromBytes(lpDigest)
    ' Hex <-- File
    strDigest = hashHexFromFile("abc.txt", PKI_HASH_SHA256) ' "abc" in a text file
    Debug.Print strDigest
    ' Bytes <-- File
    lpDigest = hashFile("abc.txt", PKI_HASH_SHA256)
    Debug.Print cnvHexStrFromBytes(lpDigest)
    
    Debug.Print "OK=" & "BA7816BF8F01CFEA414140DE5DAE2223B00361A396177A9CB410FF61F20015AD"
    

End Sub

Public Sub V_Test_HASH_Bytes3()
    Debug.Print "Testing HASH_Bytes vbacode ..."
    Dim strDigest As String
    Dim lpMessage() As Byte
    Dim lpDigest() As Byte
    lpDigest = hashBytes(lpMessage, PKI_HASH_SHA256)
    Debug.Print cnvHexStrFromBytes(lpDigest)
    lpDigest = hashBytes(lpMessage, PKI_HASH_SHA256)
    Debug.Print cnvHexStrFromBytes(lpDigest)
    strDigest = hashHexFromBytes(lpMessage, PKI_HASH_SHA256)
    Debug.Print strDigest
    strDigest = hashHexFromBytes(lpMessage, PKI_HASH_SHA512)
    Debug.Print strDigest
    strDigest = hashHexFromBytes(lpMessage, PKI_HASH_SHA512)
    Debug.Print strDigest

End Sub

Public Sub V_Test_HASH_File()
    Debug.Print "Testing HASH_File code ..."
        Dim nRet As Long
        Dim abDigest() As Byte
        Dim sFileName As String
        
        ' File to be hashed contains a total of 13 bytes: "hello world" plus CR-LF
        ' 68 65 6c 6c 6f 20 77 6f 72 6c 64 0d 0a   hello world..
    
        sFileName = "hello.txt"
        
        ' Pre-dimension digest array - do this each time
        ReDim abDigest(PKI_MAX_HASH_BYTES)
        
        ' Create default hash (SHA1) in binary mode
        nRet = HASH_File(abDigest(0), PKI_MAX_HASH_BYTES, sFileName, 0)
        If nRet > 0 Then ReDim Preserve abDigest(nRet - 1)
        Debug.Print nRet, cnvHexStrFromBytes(abDigest)
        
        ' Use SHA1 in "text" mode
        ReDim abDigest(PKI_MAX_HASH_BYTES)
        nRet = HASH_File(abDigest(0), PKI_MAX_HASH_BYTES, sFileName, PKI_HASH_MODE_TEXT)
        If nRet > 0 Then ReDim Preserve abDigest(nRet - 1)
        Debug.Print nRet, cnvHexStrFromBytes(abDigest)
        
        ' Use MD5
        ReDim abDigest(PKI_MAX_HASH_BYTES)
        nRet = HASH_File(abDigest(0), PKI_MAX_HASH_BYTES, sFileName, PKI_HASH_MD5)
        If nRet > 0 Then ReDim Preserve abDigest(nRet - 1)
        Debug.Print nRet, cnvHexStrFromBytes(abDigest)
        
        ' Use MD5 in "text" mode
        ReDim abDigest(PKI_MAX_HASH_BYTES)
        nRet = HASH_File(abDigest(0), PKI_MAX_HASH_BYTES, sFileName, PKI_HASH_MD5 Or PKI_HASH_MODE_TEXT)
        If nRet > 0 Then ReDim Preserve abDigest(nRet - 1)
        Debug.Print nRet, cnvHexStrFromBytes(abDigest)

End Sub

Public Sub V_Test_HASH_File2()
    Debug.Print "Testing HASH_File vbacode ..."
    Dim strDigest As String
    Dim lpMessage() As Byte
    Dim lpDigest() As Byte
    
    ' Hex <-- Hex
    strDigest = hashHexFromHex("616263", PKI_HASH_SHA256)   ' "abc" in hex
    Debug.Print strDigest
    lpMessage = StrConv("abc", vbFromUnicode)   ' "abc" in a byte array
    ' Hex <-- Bytes
    strDigest = hashHexFromBytes(lpMessage, PKI_HASH_SHA256)
    Debug.Print strDigest
    ' Bytes <-- Bytes
    lpDigest = hashBytes(lpMessage, PKI_HASH_SHA256)
    Debug.Print cnvHexStrFromBytes(lpDigest)
    ' Hex <-- File
    strDigest = hashHexFromFile("abc.txt", PKI_HASH_SHA256) ' "abc" in a text file
    Debug.Print strDigest
    ' Bytes <-- File
    lpDigest = hashFile("abc.txt", PKI_HASH_SHA256)
    Debug.Print cnvHexStrFromBytes(lpDigest)
    
    Debug.Print "OK=" & "BA7816BF8F01CFEA414140DE5DAE2223B00361A396177A9CB410FF61F20015AD"

End Sub

Public Sub V_Test_HASH_HexFromBytes()
    Debug.Print "Testing HASH_HexFromBytes code ..."
    Dim nRet As Long
    Dim sDigest As String
    Dim abMessage() As Byte
    ' Set up message to be hashed in unambiguous Byte format
    abMessage = StrConv("abc", vbFromUnicode)
    ' Pre-dimension digest string
    sDigest = String(PKI_MAX_HASH_CHARS, " ")
    ' Create default hash (SHA1)
    nRet = HASH_HexFromBytes(sDigest, Len(sDigest), abMessage(0), 3, 0)
    Debug.Print nRet, Left(sDigest, nRet)
    ' Explicitly use SHA1
    nRet = HASH_HexFromBytes(sDigest, Len(sDigest), abMessage(0), 3, PKI_HASH_SHA1)
    Debug.Print nRet, Left(sDigest, nRet)
    ' Pre-dimension digest string and use MD5
    sDigest = String(PKI_MD5_CHARS, " ")
    nRet = HASH_HexFromBytes(sDigest, Len(sDigest), abMessage(0), 3, PKI_HASH_MD5)
    Debug.Print nRet, sDigest
    ' Pre-dimension digest string and use MD2
    sDigest = String(PKI_MD5_CHARS, " ")
    nRet = HASH_HexFromBytes(sDigest, Len(sDigest), abMessage(0), 3, PKI_HASH_MD2)
    Debug.Print nRet, sDigest
    ' Make output string shorter - only get back that many chars
    sDigest = String(16, " ")
    nRet = HASH_HexFromBytes(sDigest, Len(sDigest), abMessage(0), 3, PKI_HASH_SHA1)
    Debug.Print nRet, sDigest

End Sub

Public Sub V_Test_HASH_HexFromBytes2()
    Debug.Print "Testing HASH_HexFromBytes code ..."
    Dim nRet As Long
    Dim sDigest As String
    Dim strMessage As String
    
    strMessage = "abc"
    ' Pre-dimension digest string
    sDigest = String(40, " ")
    ' Create default hash (SHA1)
    nRet = HASH_HexFromString(sDigest, Len(sDigest), strMessage, Len(strMessage), 0)
    Debug.Print nRet, sDigest

End Sub

Public Sub V_Test_HASH_HexFromBytes3()
    Debug.Print "Testing HASH_HexFromBytes vbacode ..."
    Dim strDigest As String
    Dim lpMessage() As Byte
    Dim lpDigest() As Byte
    
    ' Hex <-- Hex
    strDigest = hashHexFromHex("616263", PKI_HASH_SHA256)   ' "abc" in hex
    Debug.Print strDigest
    lpMessage = StrConv("abc", vbFromUnicode)   ' "abc" in a byte array
    ' Hex <-- Bytes
    strDigest = hashHexFromBytes(lpMessage, PKI_HASH_SHA256)
    Debug.Print strDigest
    ' Bytes <-- Bytes
    lpDigest = hashBytes(lpMessage, PKI_HASH_SHA256)
    Debug.Print cnvHexStrFromBytes(lpDigest)
    ' Hex <-- File
    strDigest = hashHexFromFile("abc.txt", PKI_HASH_SHA256) ' "abc" in a text file
    Debug.Print strDigest
    ' Bytes <-- File
    lpDigest = hashFile("abc.txt", PKI_HASH_SHA256)
    Debug.Print cnvHexStrFromBytes(lpDigest)
    Debug.Print "OK=" & "BA7816BF8F01CFEA414140DE5DAE2223B00361A396177A9CB410FF61F20015AD"

End Sub

Public Sub V_Test_HASH_HexFromBytes4()
    Debug.Print "Testing HASH_HexFromBytes vbacode ..."
    Dim strData As String
    Dim strDigest As String
    ' Our original string data
    strData = "Estándares de Electrónica de México para mañana"
    ' Compute SHA-1 hash over UTF-8 encoded byte array
    strDigest = hashHexFromBytes(cnvUTF8BytesFromLatin1(strData), PKI_HASH_SHA1)
    Debug.Print "Digest=" & strDigest
End Sub

Public Sub V_Test_HASH_HexFromFile()
    Debug.Print "Testing HASH_HexFromFile code ..."
    Dim nRet As Long
    Dim sDigest As String
    Dim sFileName As String
    
    ' File to be hashed contains a total of 13 bytes: "hello world" plus CR-LF
    ' 68 65 6c 6c 6f 20 77 6f 72 6c 64 0d 0a   hello world..
    
    sFileName = "hello.txt"
    
    ' Pre-dimension digest string
    sDigest = String(PKI_MAX_HASH_CHARS, " ")
    
    ' Create default hash (SHA1) in binary mode
    nRet = HASH_HexFromFile(sDigest, Len(sDigest), sFileName, 0)
    Debug.Print nRet, Left(sDigest, nRet)
    ' Use SHA1 in "text" mode
    nRet = HASH_HexFromFile(sDigest, Len(sDigest), sFileName, PKI_HASH_MODE_TEXT)
    Debug.Print nRet, Left(sDigest, nRet)
    ' Use MD5
    nRet = HASH_HexFromFile(sDigest, Len(sDigest), sFileName, PKI_HASH_MD5)
    Debug.Print nRet, Left(sDigest, nRet)
    ' Use MD5 in "text" mode
    nRet = HASH_HexFromFile(sDigest, Len(sDigest), sFileName, PKI_HASH_MD5 Or PKI_HASH_MODE_TEXT)
    Debug.Print nRet, Left(sDigest, nRet)

End Sub

Public Sub V_Test_HASH_HexFromFile2()
    Debug.Print "Testing HASH_HexFromFile vbacode ..."
    Dim strDigest As String
    Dim lpMessage() As Byte
    Dim lpDigest() As Byte
    
    ' Hex <-- Hex
    strDigest = hashHexFromHex("616263", PKI_HASH_SHA256)   ' "abc" in hex
    Debug.Print strDigest
    lpMessage = StrConv("abc", vbFromUnicode)   ' "abc" in a byte array
    ' Hex <-- Bytes
    strDigest = hashHexFromBytes(lpMessage, PKI_HASH_SHA256)
    Debug.Print strDigest
    ' Bytes <-- Bytes
    lpDigest = hashBytes(lpMessage, PKI_HASH_SHA256)
    Debug.Print cnvHexStrFromBytes(lpDigest)
    ' Hex <-- File
    strDigest = hashHexFromFile("abc.txt", PKI_HASH_SHA256) ' "abc" in a text file
    Debug.Print strDigest
    ' Bytes <-- File
    lpDigest = hashFile("abc.txt", PKI_HASH_SHA256)
    Debug.Print cnvHexStrFromBytes(lpDigest)
    
    Debug.Print "OK=" & "BA7816BF8F01CFEA414140DE5DAE2223B00361A396177A9CB410FF61F20015AD"

End Sub

Public Sub V_Test_HASH_HexFromHex()
    Debug.Print "Testing HASH_HexFromHex code ..."
    Dim strDigest As String
    Dim nRet As Long
    Dim strData As String
    ' Compute SHA-1("abc")
    strDigest = String(PKI_SHA1_CHARS, " ")
    strData = "616263"
    nRet = HASH_HexFromHex(strDigest, Len(strDigest), strData, PKI_HASH_SHA1)
    Debug.Print strDigest
    ' Compute SHA-224("abc")
    strDigest = String(PKI_SHA224_CHARS, " ")
    strData = "616263"
    nRet = HASH_HexFromHex(strDigest, Len(strDigest), strData, PKI_HASH_SHA224)
    Debug.Print strDigest

End Sub

Public Sub V_Test_HASH_HexFromHex2()
    Debug.Print "Testing HASH_HexFromHex vbacode ..."
    Dim strDigest As String
    Dim lpMessage() As Byte
    Dim lpDigest() As Byte
    
    ' Hex <-- Hex
    strDigest = hashHexFromHex("616263", PKI_HASH_SHA256)   ' "abc" in hex
    Debug.Print strDigest
    lpMessage = StrConv("abc", vbFromUnicode)   ' "abc" in a byte array
    ' Hex <-- Bytes
    strDigest = hashHexFromBytes(lpMessage, PKI_HASH_SHA256)
    Debug.Print strDigest
    ' Bytes <-- Bytes
    lpDigest = hashBytes(lpMessage, PKI_HASH_SHA256)
    Debug.Print cnvHexStrFromBytes(lpDigest)
    ' Hex <-- File
    strDigest = hashHexFromFile("abc.txt", PKI_HASH_SHA256) ' "abc" in a text file
    Debug.Print strDigest
    ' Bytes <-- File
    lpDigest = hashFile("abc.txt", PKI_HASH_SHA256)
    Debug.Print cnvHexStrFromBytes(lpDigest)
    
    Debug.Print "OK=" & "BA7816BF8F01CFEA414140DE5DAE2223B00361A396177A9CB410FF61F20015AD"

End Sub

Public Sub V_Test_HASH_Length()
    Debug.Print "Testing HASH_Length code ..."
    Debug.Print HASH_Length(PKI_HASH_SHA512)
    ' 64

End Sub

Public Sub V_Test_HASH_Length2()
    Debug.Print "Testing HASH_Length vbacode ..."
    Debug.Print hashLength(PKI_HASH_BTC160)
    ' 20

End Sub

Public Sub V_Test_HMAC_Bytes()
    Debug.Print "Testing HMAC_Bytes code ..."
    Dim abData() As Byte
    Dim abKey() As Byte
    Dim nDataLen As Long
    Dim nKeyLen As Long
    Dim abDigest() As Byte
    Dim nDigLen As Long
    Dim nRet As Long
    Dim i As Long
    
    ' Test case 4 from RFC 2202 and RFC 4231
    ' key =           0x0102030405060708090a0b0c0d0e0f10111213141516171819
    ' key_len         25
    ' data =          0xcd repeated 50 times
    ' data_len =      50
    
    nKeyLen = 25
    ReDim abKey(nKeyLen - 1)
    For i = 0 To nKeyLen - 1
        abKey(i) = CByte(i + 1)
    Next
    Debug.Print "Key=" & cnvHexStrFromBytes(abKey)
    nDataLen = 50
    ReDim abData(nDataLen - 1)
    For i = 0 To nDataLen - 1
        abData(i) = &HCD
    Next
    
    ' Compute default HMAC (HMAC-SHA-1)
    nDigLen = PKI_SHA1_BYTES
    ReDim abDigest(nDigLen - 1)
    nRet = HMAC_Bytes(abDigest(0), nDigLen, abData(0), nDataLen, abKey(0), nKeyLen, PKI_HASH_SHA1)
    If nRet <= 0 Then Exit Sub ' ERROR
    Debug.Print "HMAC-SHA-1  =" & cnvHexStrFromBytes(abDigest)
    Debug.Print "CORRECT     =" & "4c9007f4026250c6bc8414f9bf50c86c2d7235da"
    
    ' Compute HMAC-MD5
    nDigLen = PKI_MD5_BYTES
    ReDim abDigest(nDigLen - 1)
    nRet = HMAC_Bytes(abDigest(0), nDigLen, abData(0), nDataLen, abKey(0), nKeyLen, PKI_HASH_MD5)
    If nRet <= 0 Then Exit Sub ' ERROR
    Debug.Print "HMAC-MD5    =" & cnvHexStrFromBytes(abDigest)
    Debug.Print "CORRECT     =" & "697eaf0aca3a3aea3a75164746ffaa79"
    
    ' Compute HMAC-SHA-256
    nDigLen = PKI_SHA256_BYTES
    ReDim abDigest(nDigLen - 1)
    nRet = HMAC_Bytes(abDigest(0), nDigLen, abData(0), nDataLen, abKey(0), nKeyLen, PKI_HASH_SHA256)
    If nRet <= 0 Then Exit Sub ' ERROR
    Debug.Print "HMAC-SHA-256=" & cnvHexStrFromBytes(abDigest)
    Debug.Print "CORRECT     =" & "82558a389a443c0ea4cc819899f2083a85f0faa3e578f8077a2e3ff46729665b"

End Sub

Public Sub V_Test_HMAC_Bytes2()
    Debug.Print "Testing HMAC_Bytes vbacode ..."
    Dim strDigest As String
    Dim lpMessage() As Byte
    Dim lpDigest() As Byte
    Dim lpKey() As Byte
    lpKey = cnvBytesFromHexStr("0102030405060708090a0b0c0d0e0f10111213141516171819")
    lpDigest = hmacBytes(lpMessage, lpKey, PKI_HASH_SHA256)
    Debug.Print cnvHexStrFromBytes(lpDigest)
    lpDigest = hmacBytes(lpMessage, lpKey, PKI_HASH_SHA256)
    Debug.Print cnvHexStrFromBytes(lpDigest)
    strDigest = hmacHexFromBytes(lpMessage, lpKey, PKI_HASH_SHA256)
    Debug.Print strDigest
    strDigest = hmacHexFromBytes(lpMessage, lpKey, PKI_HASH_SHA512)
    Debug.Print strDigest
    strDigest = hmacHexFromBytes(lpMessage, lpKey, PKI_HASH_SHA512)
    Debug.Print strDigest
    

End Sub

Public Sub V_Test_HMAC_Bytes3()
    Debug.Print "Testing HMAC_Bytes vbacode ..."
    Dim lpData() As Byte
    Dim lpKey() As Byte
    Dim lpDigest() As Byte
    Dim strDigest As String
    
    ' Test case 4 from RFC 2202 and RFC 4231
    lpKey = cnvBytesFromHexStr("0102030405060708090a0b0c0d0e0f10111213141516171819")
    ' data = 0xcd repeated 50 times
    lpData = cnvBytesFromHexStr("cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd" & _
        "cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd")
    ' Bytes <-- Bytes
    lpDigest = hmacBytes(lpData, lpKey, PKI_HASH_SHA256)
    Debug.Print "HMAC-SHA-256=" & cnvHexStrFromBytes(lpDigest)
    Debug.Print "CORRECT     =82558a389a443c0ea4cc819899f2083a85f0faa3e578f8077a2e3ff46729665b"
    ' Hex <-- Bytes
    strDigest = hmacHexFromBytes(lpData, lpKey, PKI_HASH_SHA256)
    Debug.Print "HMAC-SHA-256=" & strDigest
    
    ' Hex <-- Hex
    ' Test case 1 from RFC 2202 and RFC 4231
    ' Data = "Hi There"
    strDigest = hmacHexFromHex("4869205468657265", "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b", PKI_HASH_SHA256)
    Debug.Print "HMAC-SHA-256=" & strDigest
    Debug.Print "CORRECT     =b0344c61d8db38535ca8afceaf0bf12b881dc200c9833da726e9376c2e32cff7"

End Sub

Public Sub V_Test_HMAC_HexFromBytes()
    Debug.Print "Testing HMAC_HexFromBytes code ..."
    Dim strData As String
    Dim strKey As String
    Dim abData() As Byte
    Dim abKey() As Byte
    Dim nDataLen As Long
    Dim nKeyLen As Long
    Dim strDigest As String
    Dim nRet As Long
    
    ' Test case 2 from RFC 2202 and RFC 4231
    strData = "what do ya want for nothing?"
    strKey = "Jefe"
    
    ' Convert message and key into Byte format
    abData = StrConv(strData, vbFromUnicode)
    abKey = StrConv(strKey, vbFromUnicode)
    nDataLen = UBound(abData) - LBound(abData) + 1
    nKeyLen = UBound(abKey) - LBound(abKey) + 1
    
    ' Dimension the output string to receive the digest
    strDigest = String(PKI_MAX_HASH_CHARS, " ")
    
    ' Compute default HMAC (HMAC-SHA-1)
    nRet = HMAC_HexFromBytes(strDigest, Len(strDigest), abData(0), nDataLen, abKey(0), nKeyLen, 0)
    If nRet <= 0 Then Exit Sub ' ERROR
    strDigest = Left(strDigest, nRet)
    Debug.Print "HMAC-SHA-1  =" & strDigest
    Debug.Print "CORRECT     =" & "effcdf6ae5eb2fa2d27416d5f184df9c259a7c79"
    
    ' Compute HMAC-MD5
    strDigest = String(PKI_MAX_HASH_CHARS, " ")
    nRet = HMAC_HexFromBytes(strDigest, Len(strDigest), abData(0), nDataLen, abKey(0), nKeyLen, PKI_HASH_MD5)
    If nRet <= 0 Then Exit Sub ' ERROR
    strDigest = Left(strDigest, nRet)
    Debug.Print "HMAC-MD5    =" & strDigest
    Debug.Print "CORRECT     =" & "750c783e6ab0b503eaa86e310a5db738"
    
    ' Compute HMAC-SHA-256
    strDigest = String(PKI_MAX_HASH_CHARS, " ")
    nRet = HMAC_HexFromBytes(strDigest, Len(strDigest), abData(0), nDataLen, abKey(0), nKeyLen, PKI_HASH_SHA256)
    If nRet <= 0 Then Exit Sub ' ERROR
    strDigest = Left(strDigest, nRet)
    Debug.Print "HMAC-SHA-256=" & strDigest
    Debug.Print "CORRECT     =" & "5bdcc146bf60754e6a042426089575c75a003f089d2739839dec58b964ec3843"
    
    ' Compute HMAC-SHA-512
    strDigest = String(PKI_MAX_HASH_CHARS, " ")
    nRet = HMAC_HexFromBytes(strDigest, Len(strDigest), abData(0), nDataLen, abKey(0), nKeyLen, PKI_HASH_SHA512)
    If nRet <= 0 Then Exit Sub ' ERROR
    strDigest = Left(strDigest, nRet)
    Debug.Print "HMAC-SHA-512=" & strDigest
    Debug.Print "CORRECT     =" _
    & "164b7a7bfcf819e2e395fbe73b56e0a387bd64222e831fd610270cd7ea250554" _
    & "9758bf75c05a994a6d034f65f8f0e6fdcaeab1a34d4a6b4b636e070a38bce737" _

End Sub

Public Sub V_Test_HMAC_HexFromBytes2()
    Debug.Print "Testing HMAC_HexFromBytes vbacode ..."
    Dim strDigest As String
    Dim lpMessage() As Byte
    Dim lpDigest() As Byte
    Dim lpKey() As Byte
    lpKey = cnvBytesFromHexStr("0102030405060708090a0b0c0d0e0f10111213141516171819")
    lpDigest = hmacBytes(lpMessage, lpKey, PKI_HASH_SHA256)
    Debug.Print cnvHexStrFromBytes(lpDigest)
    lpDigest = hmacBytes(lpMessage, lpKey, PKI_HASH_SHA256)
    Debug.Print cnvHexStrFromBytes(lpDigest)
    strDigest = hmacHexFromBytes(lpMessage, lpKey, PKI_HASH_SHA256)
    Debug.Print strDigest
    strDigest = hmacHexFromBytes(lpMessage, lpKey, PKI_HASH_SHA512)
    Debug.Print strDigest
    strDigest = hmacHexFromBytes(lpMessage, lpKey, PKI_HASH_SHA512)
    Debug.Print strDigest
    

End Sub

Public Sub V_Test_HMAC_HexFromHex()
    Debug.Print "Testing HMAC_HexFromHex code ..."
    Dim strDigest As String
    Dim nRet As Long
    Dim strData As String
    Dim strKey As String
    ' Ref: RFC 2202 and RFC 4231
    ' Test Case 1
    ' Key =  0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b
    '        0b0b0b0b                    (20 bytes)
    ' Data = 4869205468657265            ("Hi There")
    
    ' Compute HMAC-SHA-1
    strDigest = String(PKI_SHA1_CHARS, " ")
    strData = "4869205468657265"
    strKey = "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b"
    nRet = HMAC_HexFromHex(strDigest, Len(strDigest), strData, strKey, PKI_HASH_SHA1)
    Debug.Print strDigest
    ' Compute HMAC-SHA-256
    strDigest = String(PKI_SHA256_CHARS, " ")
    nRet = HMAC_HexFromHex(strDigest, Len(strDigest), strData, strKey, PKI_HASH_SHA256)
    Debug.Print strDigest

End Sub

Public Sub V_Test_HMAC_HexFromHex2()
    Debug.Print "Testing HMAC_HexFromHex vbacode ..."
    Dim lpData() As Byte
    Dim lpKey() As Byte
    Dim lpDigest() As Byte
    Dim strDigest As String
    
    ' Test case 4 from RFC 2202 and RFC 4231
    lpKey = cnvBytesFromHexStr("0102030405060708090a0b0c0d0e0f10111213141516171819")
    ' data = 0xcd repeated 50 times
    lpData = cnvBytesFromHexStr("cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd" & _
        "cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd")
    ' Bytes <-- Bytes
    lpDigest = hmacBytes(lpData, lpKey, PKI_HASH_SHA256)
    Debug.Print "HMAC-SHA-256=" & cnvHexStrFromBytes(lpDigest)
    Debug.Print "CORRECT     =82558a389a443c0ea4cc819899f2083a85f0faa3e578f8077a2e3ff46729665b"
    ' Hex <-- Bytes
    strDigest = hmacHexFromBytes(lpData, lpKey, PKI_HASH_SHA256)
    Debug.Print "HMAC-SHA-256=" & strDigest
    
    ' Hex <-- Hex
    ' Test case 1 from RFC 2202 and RFC 4231
    ' Data = "Hi There"
    strDigest = hmacHexFromHex("4869205468657265", "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b", PKI_HASH_SHA256)
    Debug.Print "HMAC-SHA-256=" & strDigest
    Debug.Print "CORRECT     =b0344c61d8db38535ca8afceaf0bf12b881dc200c9833da726e9376c2e32cff7"

End Sub

Public Sub V_Test_KDF_Bytes()
    Debug.Print "Testing KDF_Bytes code ..."
    Dim nBytes As Long
    Dim lpOutput() As Byte
    Dim lpZZ() As Byte
    Dim lpInfo() As Byte
    Dim r As Long
    
    ' ansx963_2001.rsp
    ' # CAVS 12.0
    ' # 'ANS X9.63-2001' information for sample
    ' [SHA-256]
    ' [shared secret length = 192]
    ' [SharedInfo length = 0]
    ' [key data length = 128]
    ' COUNT = 0
    ' Z = 96c05619d56c328ab95fe84b18264b08725b85e33fd34f08
    ' SharedInfo =
    ' key_data = 443024c3dae66b95e6f5670601558f71
    nBytes = 128 \ 8
    ReDim lpOutput(nBytes - 1)
    lpZZ = cnvFromHex("96c05619d56c328ab95fe84b18264b08725b85e33fd34f08")
    r = KDF_Bytes(lpOutput(0), nBytes, lpZZ(0), cnvBytesLen(lpZZ), ByVal 0&, 0, "", PKI_KDF_X963 Or PKI_HASH_SHA256)
    Debug.Print "KDF_Bytes returns " & r
    Debug.Print "KEK=" & cnvToHex(lpOutput)
    Debug.Print "OK =" & "443024c3dae66b95e6f5670601558f71"
    
    ' [RFC 5869] A.1.  Test Case 1 Basic test case with SHA-256
    nBytes = 42
    ReDim lpOutput(nBytes - 1)
    lpZZ = cnvFromHex("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b")   ' 22 octets
    lpInfo = cnvFromHex("f0f1f2f3f4f5f6f7f8f9")  ' 10 octets
    r = KDF_Bytes(lpOutput(0), nBytes, lpZZ(0), cnvBytesLen(lpZZ), lpInfo(0), cnvBytesLen(lpInfo), "salt=000102030405060708090a0b0c", PKI_KDF_HKDF Or PKI_HASH_SHA256)
    Debug.Print "KDF_Bytes returns " & r
    Debug.Print "KEK=" & cnvToHex(lpOutput)
    Debug.Print "OK =" & "3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf34007208d5b887185865"

End Sub

Public Sub V_Test_KDF_Bytes2()
    Debug.Print "Testing KDF_Bytes vbacode ..."
    Dim lpKEK() As Byte
    Dim lpZZ() As Byte
    Dim lpInfo() As Byte
    
    ' ansx963_2001.rsp CAVS 12.0 'ANS X9.63-2001' information for sample
    lpZZ = cnvFromHex("96c05619d56c328ab95fe84b18264b08725b85e33fd34f08")
    lpKEK = kdfBytes(128 \ 8, lpZZ, lpInfo, PKI_HASH_SHA256)
    Debug.Print "KEK = " & cnvHexStrFromBytes(lpKEK)
    Debug.Print "OK  = 443024c3dae66b95e6f5670601558f71"
    
    ' [RFC 5869] A.1.  Test Case 1 Basic test case with SHA-256
    lpZZ = cnvFromHex("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b")
    lpInfo = cnvFromHex("f0f1f2f3f4f5f6f7f8f9")
    lpKEK = kdfBytes(42, lpZZ, lpInfo, PKI_KDF_HKDF Or PKI_HASH_SHA256, "salt=000102030405060708090a0b0c")
    Debug.Print "KEK = " & cnvHexStrFromBytes(lpKEK)
    Debug.Print "OK  = 3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf34007208d5b887185865"

End Sub

Public Sub V_Test_KDF_ForCms()
    Debug.Print "Testing KDF_ForCms code ..."
    Dim nBytes As Long
    Dim lpOutput() As Byte
    Dim lpZZ() As Byte
    Dim lpUkm() As Byte
    
    lpZZ = cnvFromHex("160E3F5588C6FB4E9CEE8BC3C1C5000AB86396468C3D1CAEC0CB6E21536B5513")
    ' How many bytes for specified key wrap algorithm?
    nBytes = KDF_ForCms(ByVal 0&, 0, lpZZ(0), cnvBytesLen(lpZZ), ByVal 0&, 0, "", PKI_KWRAP_AES128 Or PKI_KDF_X963 Or PKI_HASH_SHA1)
    Debug.Print "KDF_ForCms returns " & nBytes
    Debug.Assert (nBytes > 0)
    ReDim lpOutput(nBytes - 1)
    nBytes = KDF_ForCms(lpOutput(0), nBytes, lpZZ(0), cnvBytesLen(lpZZ), ByVal 0&, 0, "", PKI_KWRAP_AES128 Or PKI_KDF_X963 Or PKI_HASH_SHA1)
    Debug.Print "KEK=" & cnvToHex(lpOutput)
    Debug.Print "OK =" & "04D616C654CDF62BB186A5A088B60FB5"
    
    lpUkm = cnvFromHex("616263")    ' "abc"
    nBytes = KDF_ForCms(ByVal 0&, 0, lpZZ(0), cnvBytesLen(lpZZ), lpUkm(0), cnvBytesLen(lpUkm), "", PKI_KWRAP_AES256 Or PKI_KDF_HKDF Or PKI_HASH_SHA256)
    Debug.Print "KDF_ForCms returns " & nBytes
    Debug.Assert (nBytes > 0)
    ReDim lpOutput(nBytes - 1)
    nBytes = KDF_ForCms(lpOutput(0), nBytes, lpZZ(0), cnvBytesLen(lpZZ), lpUkm(0), cnvBytesLen(lpUkm), "", PKI_KWRAP_AES256 Or PKI_KDF_HKDF Or PKI_HASH_SHA256)
    Debug.Print "KEK=" & cnvToHex(lpOutput)
    Debug.Print "OK =" & "1D06D6FD5C1EBFB33CAD875E6B99781D3D750875F573C9093CECBFBA6937ACC5"

End Sub

Public Sub V_Test_KDF_ForCms2()
    Debug.Print "Testing KDF_ForCms vbacode ..."
    Dim lpKEK() As Byte
    Dim lpZZ() As Byte
    Dim lpUkm() As Byte
    
    lpZZ = cnvFromHex("160E3F5588C6FB4E9CEE8BC3C1C5000AB86396468C3D1CAEC0CB6E21536B5513")
    lpKEK = kdfForCms(lpZZ, lpUkm, PKI_KWRAP_AES128 Or PKI_KDF_X963 Or PKI_HASH_SHA1)
    Debug.Print "KEK = " & cnvHexStrFromBytes(lpKEK)
    Debug.Print "OK  = 04D616C654CDF62BB186A5A088B60FB5"
    
    lpUkm = cnvFromHex("616263")    ' "abc"
    lpKEK = kdfForCms(lpZZ, lpUkm, PKI_KWRAP_AES256 Or PKI_KDF_HKDF Or PKI_HASH_SHA256)
    Debug.Print "KEK = " & cnvHexStrFromBytes(lpKEK)
    Debug.Print "OK  = 1D06D6FD5C1EBFB33CAD875E6B99781D3D750875F573C9093CECBFBA6937ACC5"

End Sub

Public Sub V_Test_OCSP_MakeRequest()
    Debug.Print "Testing OCSP_MakeRequest code ..."
    Dim nChars As Long
    Dim strCertFile As String
    Dim strIssuerFile As String
    Dim strBuf As String
    
    strIssuerFile = "UTNUSERFirst-Object.cer"
    strCertFile = "dims.cer"
    
    Debug.Print "IssuerFile=" & strIssuerFile
    Debug.Print "CertFile=" & strCertFile
    ' Find required length (or error)
    nChars = OCSP_MakeRequest("", 0, strIssuerFile, strCertFile, "", 0)
    Debug.Print "OCSP_MakeRequest returns " & nChars & "(expected +ve)"
    If (nChars <= 0) Then Exit Sub   ' ERROR
    strBuf = String(nChars, " ")
    nChars = OCSP_MakeRequest(strBuf, nChars, strIssuerFile, strCertFile, "", 0)
    Debug.Print "OCSPRequest=" & strBuf
    
    ' Pass a hex serial number instead of filename
    strCertFile = "#x 00 FB C7 23 22 8C 8C 80 22 D8 85 92 23 DE E7 06 60"
    Debug.Print "Cert SerialNumber=" & strCertFile
    nChars = OCSP_MakeRequest("", 0, strIssuerFile, strCertFile, "", 0)
    Debug.Print "OCSP_MakeRequest returns " & nChars & "(expected +ve)"
    If (nChars <= 0) Then Exit Sub   ' ERROR
    strBuf = String(nChars, " ")
    nChars = OCSP_MakeRequest(strBuf, nChars, strIssuerFile, strCertFile, "", 0)
    Debug.Print "OCSPRequest=" & strBuf

End Sub

Public Sub V_Test_OCSP_MakeRequest2()
    Debug.Print "Testing OCSP_MakeRequest vbacode ..."
    Dim strOcsp As String
    strOcsp = ocspMakeRequest("UTNUSERFirst-Object.cer", "dims.cer", PKI_HASH_SHA1)
    Debug.Print strOcsp
    ' Pass serial number instead of filename
    strOcsp = ocspMakeRequest("UTNUSERFirst-Object.cer", "#x 00 FB C7 23 22 8C 8C 80 22 D8 85 92 23 DE E7 06 60", PKI_HASH_SHA1)
    Debug.Print strOcsp
End Sub

Public Sub V_Test_OCSP_ReadResponse()
    Debug.Print "Testing OCSP_ReadResponse code ..."
    Dim nChars As Long
    Dim strResponseFile As String
    Dim strIssuerFile As String
    Dim strBuf As String
    strResponseFile = "ocsp_response_ok_dims.dat"
    strIssuerFile = "UTNUSERFirst-Object.cer"
    Debug.Print "ResponseFile=" & strResponseFile
    Debug.Print "IssuerFile=" & strIssuerFile
    nChars = OCSP_ReadResponse("", 0, strResponseFile, strIssuerFile, "", 0)
    Debug.Print "OCSP_ReadResponse returns " & nChars & " (expected +ve)"
    If (nChars <= 0) Then Exit Sub   ' ERROR
    strBuf = String(nChars, " ")
    nChars = OCSP_ReadResponse(strBuf, nChars, strResponseFile, strIssuerFile, "", 0)
    Debug.Print "OCSPResponse=" & strBuf

End Sub

Public Sub V_Test_OCSP_ReadResponse2()
    Debug.Print "Testing OCSP_ReadResponse vbacode ..."
    Dim strBuf As String
    strBuf = ocspReadResponse("ocsp_response_ok_dims.dat", "UTNUSERFirst-Object.cer")
    Debug.Print strBuf
End Sub

Public Sub V_Test_PAD_BytesBlock()
    Debug.Print "Testing PAD_BytesBlock code ..."
    Dim abInput() As Byte
    Dim abOutput() As Byte
    Dim nOutputLen As Long
    Dim nInputLen As Long
    Dim nBlockLen As Long
    Dim i As Long
    
    ' Prepare test input 5 bytes long
    nInputLen = 5
    ReDim abInput(nInputLen - 1)
    For i = 0 To nInputLen - 1
        abInput(i) = &HFF
    Next
    Debug.Print "Input data=0x" & cnvHexStrFromBytes(abInput)
    
    ' Find out the required length
    nBlockLen = 8
    nOutputLen = PAD_BytesBlock(vbNull, 0, abInput(0), nInputLen, nBlockLen, 0)
    Debug.Print "Required length is " & nOutputLen & " bytes"
    ' Check for error
    If (nOutputLen <= 0) Then Exit Sub
    
    ' Pre-dimension output
    ReDim abOutput(nOutputLen - 1)
    
    nOutputLen = PAD_BytesBlock(abOutput(0), nOutputLen, abInput(0), nInputLen, nBlockLen, 0)
    Debug.Print "Padded data=0x" & cnvHexStrFromBytes(abOutput)
    
    ' Now set input as padded output and remove padding
    abInput = abOutput
    nInputLen = nOutputLen
    
    ' Remove padding...
    ' No need to query for length because we know the output will be shorter than input
    ' so make sure output is as long as the input
    nOutputLen = nInputLen
    ReDim abOutput(nOutputLen - 1)
    nOutputLen = PAD_UnpadBytes(abOutput(0), nOutputLen, abInput(0), nInputLen, nBlockLen, 0)
    Debug.Print "Unpadded length is " & nOutputLen & " bytes"
    ' Check for error
    If (nOutputLen < 0) Then Exit Sub
    ' Truncate the output to the correct length
    If nOutputLen > 0 Then
        ReDim Preserve abOutput(nOutputLen - 1)
    Else
        ' Catch zero-length output
        abOutput = vbNullString
    End If
    Debug.Print "Unpadded data=0x" & cnvHexStrFromBytes(abOutput)

End Sub

Public Sub V_Test_PAD_BytesBlock2()
    Debug.Print "Testing PAD_BytesBlock vbacode ..."
    Dim lpInput() As Byte
    Dim lpBlock() As Byte
    Dim lpUnpadded() As Byte
    lpInput = cnvBytesFromHexStr("FDFDFDFDFD")
    Debug.Print "Input data =  0x" & cnvHexStrFromBytes(lpInput)
    lpBlock = padBytesBlock(lpInput, 8, 0)
    Debug.Print "Padded data = 0x" & cnvHexStrFromBytes(lpBlock)
    ' Unpad
    lpUnpadded = padUnpadBytes(lpBlock, 8, 0)
    Debug.Print "Unpadded data = 0x" & cnvHexStrFromBytes(lpUnpadded)
    
    ' Special corner case - output is the empty string
    lpBlock = cnvBytesFromHexStr("0808080808080808")
    Debug.Print "Padded data = 0x" & cnvHexStrFromBytes(lpBlock)
    lpUnpadded = padUnpadBytes(lpBlock, 8, 0)
    Debug.Print "Unpadded data = 0x" & cnvHexStrFromBytes(lpUnpadded)
End Sub

Public Sub V_Test_PAD_HexBlock()
    Debug.Print "Testing PAD_HexBlock code ..."
    Dim strInputHex As String
    Dim strOutputHex As String
    Dim nOutChars As Long
    Dim nBlockLen As Long
    Dim i As Long
    
    ' Prepare test input 5 bytes long
    strInputHex = "FFFFFFFFFF"
    Debug.Print "Input data='" & strInputHex & "'"
    
    ' Find out the required number of characters in output
    nBlockLen = 8   ' NB block length is in bytes
    nOutChars = PAD_HexBlock("", 0, strInputHex, nBlockLen, 0)
    Debug.Print "Required length is " & nOutChars & " characters"
    ' Check for error
    If (nOutChars <= 0) Then Exit Sub
    
    ' Pre-dimension output
    strOutputHex = String(nOutChars, " ")
    
    nOutChars = PAD_HexBlock(strOutputHex, Len(strOutputHex), strInputHex, nBlockLen, 0)
    Debug.Print "Padded data='" & strOutputHex & "'"
    
    ' Now set input as padded output and remove padding
    strInputHex = strOutputHex
    
    ' Remove padding...
    ' No need to query for length because we know the output will be shorter than input
    ' so make sure output is as long as the input
    strOutputHex = String(Len(strInputHex), " ")
    nOutChars = PAD_UnpadHex(strOutputHex, Len(strOutputHex), strInputHex, nBlockLen, 0)
    Debug.Print "Unpadded length is " & nOutChars & " characters"
    ' Check for error
    If (nOutChars <= 0) Then Exit Sub
    
    ' Re-dimension the output to the correct length
    strOutputHex = Left$(strOutputHex, nOutChars)
    Debug.Print "Unpadded data='" & strOutputHex & "'"

End Sub

Public Sub V_Test_PAD_HexBlock2()
    Debug.Print "Testing PAD_HexBlock vbacode ..."
    Dim strInputHex As String
    Dim strOutputHex As String
    strInputHex = "FDFDFD"
    Debug.Print "Hex input  =" & strInputHex
    
    strOutputHex = padHexBlock(strInputHex, 8, 0)
    Debug.Print "Padded data=" & strOutputHex
    Debug.Print "Unpadded   =" & padUnpadHex(strOutputHex, 8, 0)
    
    strOutputHex = padHexBlock(strInputHex, 8, PKI_PAD_1ZERO)
    Debug.Print "Padded data=" & strOutputHex
    Debug.Print "Unpadded   =" & padUnpadHex(strOutputHex, 8, PKI_PAD_1ZERO)
    
    strOutputHex = padHexBlock(strInputHex, 8, PKI_PAD_AX923)
    Debug.Print "Padded data=" & strOutputHex
    Debug.Print "Unpadded   =" & padUnpadHex(strOutputHex, 8, PKI_PAD_AX923)

End Sub

Public Sub V_Test_PAD_UnpadBytes()
    Debug.Print "Testing PAD_UnpadBytes vbacode ..."
    Dim lpInput() As Byte
    Dim lpBlock() As Byte
    Dim lpUnpadded() As Byte
    lpInput = cnvBytesFromHexStr("FDFDFDFDFD")
    Debug.Print "Input data =  0x" & cnvHexStrFromBytes(lpInput)
    lpBlock = padBytesBlock(lpInput, 8, 0)
    Debug.Print "Padded data = 0x" & cnvHexStrFromBytes(lpBlock)
    ' Unpad
    lpUnpadded = padUnpadBytes(lpBlock, 8, 0)
    Debug.Print "Unpadded data = 0x" & cnvHexStrFromBytes(lpUnpadded)
    
    ' Special corner case - output is the empty string
    lpBlock = cnvBytesFromHexStr("0808080808080808")
    Debug.Print "Padded data = 0x" & cnvHexStrFromBytes(lpBlock)
    lpUnpadded = padUnpadBytes(lpBlock, 8, 0)
    Debug.Print "Unpadded data = 0x" & cnvHexStrFromBytes(lpUnpadded)
End Sub

Public Sub V_Test_PAD_UnpadHex()
    Debug.Print "Testing PAD_UnpadHex vbacode ..."
    Dim strInputHex As String
    Dim strOutputHex As String
    strInputHex = "FDFDFD"
    Debug.Print "Hex input  =" & strInputHex
    
    strOutputHex = padHexBlock(strInputHex, 8, 0)
    Debug.Print "Padded data=" & strOutputHex
    Debug.Print "Unpadded   =" & padUnpadHex(strOutputHex, 8, 0)
    
    strOutputHex = padHexBlock(strInputHex, 8, PKI_PAD_1ZERO)
    Debug.Print "Padded data=" & strOutputHex
    Debug.Print "Unpadded   =" & padUnpadHex(strOutputHex, 8, PKI_PAD_1ZERO)
    
    strOutputHex = padHexBlock(strInputHex, 8, PKI_PAD_AX923)
    Debug.Print "Padded data=" & strOutputHex
    Debug.Print "Unpadded   =" & padUnpadHex(strOutputHex, 8, PKI_PAD_AX923)
    

End Sub

Public Sub V_Test_PAD_UnpadHex2()
    Debug.Print "Testing PAD_UnpadHex vbacode ..."
    Dim strInputHex As String
    Dim strOutputHex As String
    strInputHex = "FFFFFFFFFF030303"
    Debug.Print "Hex input  =" & strInputHex
    strOutputHex = padUnpadHex(strInputHex, PKI_BLK_TDEA_BYTES, 0)
    Debug.Print "Unpadded   =" & strOutputHex
    ' Output is empty string
    strInputHex = "0808080808080808"
    Debug.Print "Hex input  =" & strInputHex
    strOutputHex = padUnpadHex(strInputHex, PKI_BLK_TDEA_BYTES, 0)
    Debug.Print "Unpadded   =" & strOutputHex
    ' Bad input data results in the same data being returned
    strInputHex = "FFFFFFFFFFFFFFFF"
    Debug.Print "Hex input  =" & strInputHex
    strOutputHex = padUnpadHex(strInputHex, PKI_BLK_TDEA_BYTES, 0)
    Debug.Print "Unpadded   =" & strOutputHex
    If Len(strOutputHex) = Len(strInputHex) Then
        Debug.Print "DECRYPTION ERROR"
    End If
    Debug.Assert Len(strOutputHex) = Len(strInputHex)
End Sub

Public Sub V_Test_PBE_Kdf2()
    Debug.Print "Testing PBE_Kdf2 code ..."
        Dim abDerivedKey() As Byte
        Dim nKeyLen As Long
        Dim sPassword As String
        Dim abPwdBytes() As Byte
        Dim abSalt(7) As Byte
        Dim nCount As Long
        Dim nRet As Long
        
    ' Convert password String to an array of Bytes
        sPassword = "password"
        abPwdBytes = StrConv(sPassword, vbFromUnicode)
        
    ' Set 8-byte salt = 78 57 8E 5A 5D 63 CB 06
        abSalt(0) = &H78
        abSalt(1) = &H57
        abSalt(2) = &H8E
        abSalt(3) = &H5A
        abSalt(4) = &H5D
        abSalt(5) = &H63
        abSalt(6) = &HCB
        abSalt(7) = &H6
        
    ' Iteration count is 2048
        nCount = 2048
        
    ' Pre-dimension output for derived key to required length of 24 bytes
    ' (Don't forget to do this)
        nKeyLen = 24
        ReDim abDerivedKey(nKeyLen - 1)
        
    ' Derive PBKDF2 key using function from CryptoSys
        nRet = PBE_Kdf2(abDerivedKey(0), nKeyLen, _
          abPwdBytes(0), Len(sPassword), abSalt(0), 8&, nCount, 0&)
        
    ' Convert bytes to hex and print
        Debug.Print "Derived key = " & cnvHexStrFromBytes(abDerivedKey)
        Debug.Print "Correct key = BFDE6BE94DF7E11DD409BCE20A0255EC327CB936FFE93643"

End Sub

Public Sub V_Test_PBE_Kdf22()
    Debug.Print "Testing PBE_Kdf2 code ..."
        Dim abDerivedKey() As Byte
        Dim nKeyLen As Long
        Dim sPassword As String
        Dim abPwdBytes() As Byte
        Dim abSalt(7) As Byte
        Dim nSaltBytes As Long
        Dim nCount As Long
        Dim nRet As Long
        
    ' Convert password String to an array of Bytes
        sPassword = "password"
        abPwdBytes = StrConv(sPassword, vbFromUnicode)
        
    ' Set 8-byte salt = 78 57 8E 5A 5D 63 CB 06
        abSalt(0) = &H78
        abSalt(1) = &H57
        abSalt(2) = &H8E
        abSalt(3) = &H5A
        abSalt(4) = &H5D
        abSalt(5) = &H63
        abSalt(6) = &HCB
        abSalt(7) = &H6
        nSaltBytes = 8
        
    ' Iteration count is 2048
        nCount = 2048
        
    ' Pre-dimension output for derived key to required length of 24 bytes
    ' (Don't forget to do this)
        nKeyLen = 24
        ReDim abDerivedKey(nKeyLen - 1)
        
    ' Derive PBKDF2 key using function from CryptoSys API with default HMAC-SHA-1
        nRet = PBE_Kdf2(abDerivedKey(0), nKeyLen, _
          abPwdBytes(0), Len(sPassword), abSalt(0), nSaltBytes, nCount, PKI_HASH_SHA1)
    ' Convert bytes to hex and print
        Debug.Print "Derived key {HMAC-SHA-1}   = " & cnvHexStrFromBytes(abDerivedKey)
        
    ' Derive PBKDF2 key using function from CryptoSys API with HMAC-SHA-256
        nRet = PBE_Kdf2(abDerivedKey(0), nKeyLen, _
          abPwdBytes(0), Len(sPassword), abSalt(0), nSaltBytes, nCount, PKI_HASH_SHA256)
        Debug.Print "Derived key {HMAC-SHA-256} = " & cnvHexStrFromBytes(abDerivedKey)
    
    ' Derive PBKDF2 key using function from CryptoSys API with HMAC-SHA-224
        nRet = PBE_Kdf2(abDerivedKey(0), nKeyLen, _
          abPwdBytes(0), Len(sPassword), abSalt(0), nSaltBytes, nCount, PKI_HASH_SHA224)
        Debug.Print "Derived key {HMAC-SHA-224} = " & cnvHexStrFromBytes(abDerivedKey)

End Sub

Public Sub V_Test_PBE_Kdf23()
    Debug.Print "Testing PBE_Kdf2 vbacode ..."
    Dim lpDK() As Byte
    Dim strPassword As String
    Dim lpSalt() As Byte
    Dim nCount As Long
    strPassword = "password"
    lpSalt = cnvBytesFromHexStr("78 57 8E 5A 5D 63 CB 06")
    nCount = 2048
    lpDK = pbeKdf2(24, StrConv(strPassword, vbFromUnicode), lpSalt, nCount)
    Debug.Print "Derived key = " & cnvHexStrFromBytes(lpDK)
    Debug.Print "Correct key = BFDE6BE94DF7E11DD409BCE20A0255EC327CB936FFE93643"
    
    lpDK = pbeKdf2(24, StrConv(strPassword, vbFromUnicode), lpSalt, nCount, PKI_HASH_SHA256)
    Debug.Print "Derived key {HMAC-SHA-256} = " & cnvHexStrFromBytes(lpDK)
    Debug.Print "Correct key {HMAC-SHA-256} = 97B5A91D35AF542324881315C4F849E327C4707D1BC9D322"

End Sub

Public Sub V_Test_PBE_Kdf2Hex()
    Debug.Print "Testing PBE_Kdf2Hex code ..."
    Dim strDerivedKey As String
    Dim nKeyLen As Long
    Dim strPassword As String
    Dim strSaltHex As String
    Dim nCount As Long
    Dim nRet As Long
    
    strPassword = "password"  ' NB normal text, not hex
    
    ' Set 8-byte salt = 78 57 8E 5A 5D 63 CB 06
    strSaltHex = "78578E5A5D63CB06"
    
    ' Iteration count is 2048
    nCount = 2048
    
    ' Pre-dimension output string for derived key to
    ' required length of 24 bytes i.e. 48 hex chars
    ' (Don't forget to do this)
    nKeyLen = 24
    strDerivedKey = String(2 * nKeyLen, " ")
    
    ' Derive PBKDF2 key using function from CryptoSys API
    nRet = PBE_Kdf2Hex(strDerivedKey, Len(strDerivedKey), nKeyLen, _
        strPassword, strSaltHex, nCount, 0)
    
    ' Check against test vector
    Debug.Print "Derived key = " & strDerivedKey
    Debug.Print "Correct key = BFDE6BE94DF7E11DD409BCE20A0255EC327CB936FFE93643"

End Sub

Public Sub V_Test_PBE_Kdf2Hex2()
    Debug.Print "Testing PBE_Kdf2Hex vbacode ..."
    Dim strDK As String
    Dim strPassword As String
    Dim strSaltHex As String
    Dim nCount As Long
    strPassword = "password"
    strSaltHex = "78578E5A5D63CB06"
    nCount = 2048
    strDK = pbeKdf2Hex(24, strPassword, strSaltHex, nCount)
    Debug.Print "Derived key = " & strDK
    Debug.Print "Correct key = BFDE6BE94DF7E11DD409BCE20A0255EC327CB936FFE93643"
End Sub

Public Sub V_Test_PEM_FileFromBinFile()
    Debug.Print "Testing PEM_FileFromBinFile code ..."
    Dim nRet As Long
    Dim strBinFile As String
    Dim strPEMFile As String
    Dim strDigest As String
    
    ' Input file is a DER-encoded X.509 certificate
    ' (at 227 bytes, the smallest we could devise)
    strBinFile = "smallca.cer"
    strPEMFile = "smallca.pem.cer"
    
    ' Convert to a PEM file
    nRet = PEM_FileFromBinFile(strPEMFile, strBinFile, "CERTIFICATE", 72)
    Debug.Print "PEM_FileFromBinFile returns " & nRet & " (expecting 0)"
    
    ' To prove we did it properly, compute the thumbprint of the two certs
    strDigest = String(PKI_SHA1_CHARS, " ")
    nRet = X509_CertThumb(strBinFile, strDigest, Len(strDigest), PKI_HASH_SHA1)
    If nRet > 0 Then
        Debug.Print "SHA-1(der-file)=" & strDigest
    Else
        Debug.Print "ERROR: computing cert thumb"
    End If
    nRet = X509_CertThumb(strPEMFile, strDigest, Len(strDigest), PKI_HASH_SHA1)
    If nRet > 0 Then
        Debug.Print "SHA-1(pem-file)=" & strDigest
    Else
        Debug.Print "ERROR: computing cert thumb"
    End If

End Sub

Public Sub V_Test_PEM_FileToBinFile()
    Debug.Print "Testing PEM_FileToBinFile code ..."
    Dim nRet As Long
    Dim strBinFile As String
    Dim strPEMFile As String
    Dim strDigest As String
    
    ' Input file is a PEM-encoded X.509 certificate
    strPEMFile = "smallca.pem.cer"
    strBinFile = "smallca-copy.cer"
    
    ' Convert to a binary file
    nRet = PEM_FileToBinFile(strBinFile, strPEMFile)
    Debug.Print "PEM_FiletoBinFile returns " & nRet & " (expecting 0)"

End Sub

Public Sub V_Test_PFX_MakeFile()
    Debug.Print "Testing PFX_MakeFile code ..."
    Dim strOutputFile As String
    Dim strCertFile As String
    Dim strKeyFile As String
    Dim strPassword As String
    Dim nRet As Long
    
    strOutputFile = "Bob1.pfx"
    strCertFile = "BobRSASignByCarl.cer"
    strKeyFile = "BobPrivRSAEncrypt.p8e"
    strPassword = "password"
    
    ' Given Bob's certificate and encrypted private key file (with password "password"),
    ' create a PKCS-12 (pfx/p12) file.
    nRet = PFX_MakeFile(strOutputFile, strCertFile, strKeyFile, strPassword, "Bob's ID", 0)
    Debug.Print "PFX_MakeFile returns " & nRet
    
    ' Now verify that the signature is OK
    nRet = PFX_VerifySig(strOutputFile, strPassword, 0)
    Debug.Print "PFX_VerifySig returns " & nRet
    
    ' Clean up
    Call WIPE_String(strPassword, Len(strPassword))

End Sub

Public Sub V_Test_PFX_MakeFile2()
    Debug.Print "Testing PFX_MakeFile code ..."
    Dim strOutputFile As String
    Dim strCertFile As String
    Dim strKeyFile As String
    Dim nRet As Long
    
    strOutputFile = "CarlNoKey.p12"
    strCertFile = "CarlRSASelf.cer"
    
    ' Given Carl's certificate only,
    ' create a PKCS-12 (pfx/p12) file with no private key.
    nRet = PFX_MakeFile(strOutputFile, strCertFile, "", "", "Carl's ID", 0)
    Debug.Print "PFX_MakeFile returns " & nRet

End Sub

Public Sub V_Test_PKI_CompileTime()
    Debug.Print "Testing PKI_CompileTime code ..."
    Dim nLen As Long
    Dim strCompiledOn As String
    
    strCompiledOn = String(255, " ")
    nLen = PKI_CompileTime(strCompiledOn, Len(strCompiledOn))
    strCompiledOn = Left(strCompiledOn, nLen)
    Debug.Print "PKI_CompileTime returns " & nLen & " [" & strCompiledOn & "]"

End Sub

Public Sub V_Test_PKI_CompileTime2()
    Debug.Print "Testing PKI_CompileTime vbacode ..."
    Debug.Print pkiCompileTime()
    Debug.Print pkiModuleInfo()
    Debug.Print pkiModuleName()
    Debug.Print pkiPlatform()

End Sub

Public Sub V_Test_PKI_ErrorCode()
    Debug.Print "Testing PKI_ErrorCode code ..."
       Dim nErrCode As Long
       nErrCode = PKI_ErrorCode()

End Sub

Public Sub V_Test_PKI_ErrorLookup()
    Debug.Print "Testing PKI_ErrorLookup code ..."
    Dim nLen As Long
    Dim nErrCode As Long
    Dim strErrMsg As String * 128
    
    nErrCode = 25
    nLen = PKI_ErrorLookup(strErrMsg, Len(strErrMsg), nErrCode)
    Debug.Print "ErrorLookup(" & nErrCode & ")=" & Left(strErrMsg, nLen)

End Sub

Public Sub V_Test_PKI_ErrorLookup2()
    Debug.Print "Testing PKI_ErrorLookup vbacode ..."
    Dim nErrCode As Long
    For nErrCode = 1 To 11
        Debug.Print nErrCode & " = " & pkiErrorLookup(nErrCode)
    Next

End Sub

Public Sub V_Test_PKI_LastError()
    Debug.Print "Testing PKI_LastError vbacode ..."
    Dim s As String
    ' Valid function call, no error
    s = hashHexFromHex("616263", PKI_HASH_SHA1)
    Debug.Print "SHA1('abc')=" & s
    ' No error, so expecting empty string
    Debug.Print "LastError='" & pkiLastError() & "'"
    ' Force an error
    s = rsaFromXMLString("BADSTRING")
    Debug.Print "rsaFromXMLString(ERROR) returns '" & s & "'"
    Debug.Print "LastError='" & pkiLastError() & "'"

End Sub

Public Sub V_Test_PKI_LicenceType()
    Debug.Print "Testing PKI_LicenceType code ..."
    Dim nRet As Long
    nRet = PKI_LicenceType(0)
    Debug.Print "PKI_LicenceType is " & Chr(nRet)

End Sub

Public Sub V_Test_PKI_ModuleInfo()
    Debug.Print "Testing PKI_ModuleInfo code ..."
    Dim nLen As Long
    Dim strModuleInfo As String
    
    nLen = PKI_ModuleInfo("", 0, 0)
    If nLen > 0 Then
        strModuleInfo = String(nLen, " ")
        nLen = PKI_ModuleInfo(strModuleInfo, nLen, 0)
        strModuleInfo = Left(strModuleInfo, nLen)
        Debug.Print "PKI_ModuleInfo returns " & nLen & " [" & strModuleInfo & "]"
    Else
        Debug.Print "Error " & nLen & " with PKI_ModuleInfo"
    End If

End Sub

Public Sub V_Test_PKI_ModuleName()
    Debug.Print "Testing PKI_ModuleName code ..."
    Dim nLen As Long
    Dim strModuleName As String
    
    nLen = PKI_ModuleName("", 0, 0)
    If nLen > 0 Then
        strModuleName = String(nLen, " ")
        nLen = PKI_ModuleName(strModuleName, nLen, 0)
        strModuleName = Left(strModuleName, nLen)
        Debug.Print "PKI_ModuleName returns " & nLen & " [" & strModuleName & "]"
    Else
        Debug.Print "Error " & nLen & " with PKI_ModuleName"
    End If

End Sub

Public Sub V_Test_PKI_ModuleName2()
    Debug.Print "Testing PKI_ModuleName vbacode ..."
    Debug.Print pkiCompileTime()
    Debug.Print pkiModuleInfo()
    Debug.Print pkiModuleName()
    Debug.Print pkiPlatform()

End Sub

Public Sub V_Test_PKI_Platform()
    Debug.Print "Testing PKI_Platform vbacode ..."
    Debug.Print pkiCompileTime()
    Debug.Print pkiModuleInfo()
    Debug.Print pkiModuleName()
    Debug.Print pkiPlatform()

End Sub

Public Sub V_Test_PKI_PowerUpTests()
    Debug.Print "Testing PKI_PowerUpTests code ..."
        Dim nRet As Long
        
        nRet = PKI_PowerUpTests(0)
        Debug.Print "PKI_PowerUpTests returns " & nRet

End Sub

Public Sub V_Test_PKI_Version()
    Debug.Print "Testing PKI_Version code ..."
    Dim nRet As Long
    nRet = PKI_Version(0, 0)
    Debug.Print "PKI_Version returns " & nRet
    ' PKI_Version returns 200301

End Sub

Public Sub V_Test_PRF_Bytes()
    Debug.Print "Testing PRF_Bytes vbacode ..."
    Dim lpPrf() As Byte
    Dim lpMsg() As Byte
    Dim lpKey() As Byte
    lpKey = cnvFromHex("404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F")
    lpMsg = cnvFromHex("00010203")
    ' NB order of parameters (szCustom <=> nOptions).
    lpPrf = prfBytes(256 \ 8, lpMsg, lpKey, PKI_KMAC_128, "My Tagged Application")
    Debug.Print "KMAC=" & cnvToHex(lpPrf)
    Debug.Print "OK  =3B1FBA963CD8B0B59E8C1A6D71888B7143651AF8BA0A7070C0979E2811324AA5"

End Sub

Public Sub V_Test_RNG_Bytes()
    Debug.Print "Testing RNG_Bytes code ..."
    Dim abData() As Byte
    Dim nDataLen As Long
    
    nDataLen = 16
    ReDim abData(nDataLen - 1)
    Call RNG_Bytes(abData(0), nDataLen, "", 0)
    Debug.Print cnvHexStrFromBytes(abData)

End Sub

Public Sub V_Test_RNG_Bytes2()
    Debug.Print "Testing RNG_Bytes vbacode ..."
    Dim i As Integer
    For i = 1 To 10
        Debug.Print cnvHexStrFromBytes(rngBytes(32))
    Next
End Sub

Public Sub V_Test_RNG_Guid()
    Debug.Print "Testing RNG_Guid code ..."
    Dim strGuid As String
    strGuid = String(PKI_RNG_GUID_CHARS, " ")
    Call RNG_Guid(strGuid, Len(strGuid), 0)
    Debug.Print strGuid

End Sub

Public Sub V_Test_RNG_Guid2()
    Debug.Print "Testing RNG_Guid vbacode ..."
    Dim i As Integer
    For i = 1 To 5
        Debug.Print rngGuid()
    Next
End Sub

Public Sub V_Test_RNG_Initialize()
    Debug.Print "Testing RNG_Initialize code ..."
    Dim strSeedFile As String
    Dim nRet As Long
    Dim abData() As Byte
    Dim nDataLen As Long
    Dim i As Integer
    
    strSeedFile = "seed.dat"
    ' 1. Initialize
    nRet = RNG_Initialize(strSeedFile, 0)
    Debug.Print "RNG_Initialize('" & strSeedFile & "') returns " & nRet & " (expecting 0)"
    
    ' 2. Generate some random data
    nDataLen = 24
    ReDim abData(nDataLen - 1)
    For i = 1 To 3
        Call RNG_Bytes(abData(0), nDataLen, "", 0)
        Debug.Print cnvHexStrFromBytes(abData)
    Next
    
    ' 3. Update the seed file
    nRet = RNG_UpdateSeedFile(strSeedFile, 0)
    Debug.Print "RNG_UpdateSeedFile('" & strSeedFile & "') returns " & nRet & " (expecting 0)"

End Sub

Public Sub V_Test_RNG_Number()
    Debug.Print "Testing RNG_Number code ..."
    Dim i As Integer
    For i = 1 To 5
        Debug.Print RNG_Number(-1000000, 1000000)
    Next

End Sub

Public Sub V_Test_RNG_Test()
    Debug.Print "Testing RNG_Test code ..."
    Dim strFileName As String
    Dim nRet As Long
    
    strFileName = "pkiFips140.txt"
    nRet = RNG_Test(strFileName, 0)
    Debug.Print "RNG_Test('" & strFileName & "') returns " & nRet & " (expecting 0)"

End Sub

Public Sub V_Test_RSA_DecodeMsg()
    Debug.Print "Testing RSA_DecodeMsg code ..."
        Dim abData() As Byte
        Dim abBlock() As Byte
        Dim abDigest() As Byte
        Dim abDigInfo() As Byte
        Dim nDataLen As Long
        Dim nBlockLen As Long
        Dim nLen As Long
        Dim nRet As Long
        Dim nOptions As Long
        
        ' 0. Create an encoded test block ready for for signing
        abData = StrConv("abc", vbFromUnicode)
        nDataLen = UBound(abData) - LBound(abData) + 1
        nBlockLen = 64
        ReDim abBlock(nBlockLen - 1)
        nRet = RSA_EncodeMsg(abBlock(0), nBlockLen, abData(0), nDataLen, PKI_EMSIG_PKCSV1_5)
        Debug.Print "BLOCK   =" & cnvHexStrFromBytes(abBlock)
        
        ' 1. Extract the message digest =SHA1("abc")
        nLen = RSA_DecodeMsg(0, 0, abBlock(0), nBlockLen, PKI_EMSIG_PKCSV1_5)
        If nLen < 0 Then MsgBox "Decryption Error": Exit Sub
        Debug.Print "Message digest is " & nLen & " bytes long"
        ReDim abDigest(nLen - 1)
        nLen = RSA_DecodeMsg(abDigest(0), nLen, abBlock(0), nBlockLen, PKI_EMSIG_PKCSV1_5)
        Debug.Print "HASH    =" & cnvHexStrFromBytes(abDigest)
        
         ' 2. Extract the full DigestInfo data
        nOptions = PKI_EMSIG_PKCSV1_5 + PKI_EMSIG_DIGINFO
        nLen = RSA_DecodeMsg(0, 0, abBlock(0), nBlockLen, nOptions)
        If nLen < 0 Then MsgBox "Decryption Error": Exit Sub
        Debug.Print "DigestInfo is " & nLen & " bytes long"
        ReDim abDigest(nLen - 1)
        nLen = RSA_DecodeMsg(abDigest(0), nLen, abBlock(0), nBlockLen, nOptions)
        Debug.Print "DIGINFO=" & cnvHexStrFromBytes(abDigest)

End Sub

Public Sub V_Test_RSA_DecodeMsg2()
    Debug.Print "Testing RSA_DecodeMsg vbacode ..."
    Dim lpData() As Byte
    Dim lpBlock() As Byte
    Dim lpDecoded() As Byte
    Dim nBlockLen As Long
    nBlockLen = 512 \ 8
    
    lpData = cnvBytesFromHexStr("DEADBEEF")
    
    lpBlock = rsaEncodeMsg(nBlockLen, lpData, PKI_EME_PKCSV1_5)
    Debug.Print cnvHexStrFromBytes(lpBlock)
    lpDecoded = rsaDecodeMsg(lpBlock, PKI_EME_PKCSV1_5)
    Debug.Print "DECODED=" & cnvHexStrFromBytes(lpDecoded)
    
    lpBlock = rsaEncodeMsg(nBlockLen, lpData, PKI_EME_OAEP)
    Debug.Print cnvHexStrFromBytes(lpBlock)
    lpDecoded = rsaDecodeMsg(lpBlock, PKI_EME_OAEP)
    Debug.Print "DECODED=" & cnvHexStrFromBytes(lpDecoded)
    
    lpBlock = rsaEncodeMsg(nBlockLen, lpData, PKI_EMSIG_PKCSV1_5 Or PKI_HASH_SHA256)
    Debug.Print cnvHexStrFromBytes(lpBlock)
    lpDecoded = rsaDecodeMsg(lpBlock, PKI_EMSIG_PKCSV1_5)
    Debug.Print "DECODED=" & cnvHexStrFromBytes(lpDecoded)
    
    Debug.Print "DIGEST =" & hashHexFromBytes(lpData, PKI_HASH_SHA256)
    

End Sub

Public Sub V_Test_RSA_EncodeMsg()
    Debug.Print "Testing RSA_EncodeMsg code ..."
    Dim abData(3) As Byte
    Dim abBlock() As Byte
    Dim abCheck() As Byte
    Dim nDataLen As Long
    Dim nBlockLen As Long
    Dim nLen As Long
    Dim nRet As Long
    
    ' Our message data, 4 bytes long
    abData(0) = &HDE
    abData(1) = &HAD
    abData(2) = &HBE
    abData(3) = &HEF
    nDataLen = 4
    Debug.Print "DATA   =" & cnvHexStrFromBytes(abData)
    ' Set up output block with correct size
    nBlockLen = 64
    ReDim abBlock(nBlockLen - 1)
    ' Encode ready for encryption with default algorithm
    nRet = RSA_EncodeMsg(abBlock(0), nBlockLen, abData(0), nDataLen, PKI_EME_PKCSV1_5)
    If (nRet < 0) Then
        MsgBox "Encoding Error"
        Exit Sub
    End If
    Debug.Print "BLOCK  =" & cnvHexStrFromBytes(abBlock)
    
    ' Now encrypt this block using RSA_RawPublic
    ' ...
    ' ... and send to recipient ...
    ' ...
    ' who decrypts using RSA_RawPrivate to get the encoded block
    
    ' Recover the message from the encoded block
    ' How long is it?
    nLen = RSA_DecodeMsg(0, 0, abBlock(0), nBlockLen, PKI_EME_PKCSV1_5)
    If (nLen < 0) Then
        MsgBox "Decryption Error"
        Exit Sub
    End If
    ReDim abCheck(nLen - 1)
    nLen = RSA_DecodeMsg(abCheck(0), nLen, abBlock(0), nBlockLen, PKI_EME_PKCSV1_5)
    Debug.Print "DECODED=" & cnvHexStrFromBytes(abCheck)
    
     ' Alternative using more-secure OAEP algorithm
    nRet = RSA_EncodeMsg(abBlock(0), nBlockLen, abData(0), nDataLen, PKI_EME_OAEP)
    If (nRet < 0) Then
        MsgBox "Encoding Error"
        Exit Sub
    End If
    Debug.Print "BLOCK  =" & cnvHexStrFromBytes(abBlock)
    ' ...
    nLen = RSA_DecodeMsg(0, 0, abBlock(0), nBlockLen, PKI_EME_OAEP)
    If (nLen < 0) Then
        MsgBox "Decryption Error"
        Exit Sub
    End If
    ReDim abCheck(nLen - 1)
    nLen = RSA_DecodeMsg(abCheck(0), nLen, abBlock(0), nBlockLen, PKI_EME_OAEP)
    Debug.Print "DECODED=" & cnvHexStrFromBytes(abCheck)

End Sub

Public Sub V_Test_RSA_EncodeMsg2()
    Debug.Print "Testing RSA_EncodeMsg vbacode ..."
    Dim lpData() As Byte
    Dim lpBlock() As Byte
    Dim lpDecoded() As Byte
    Dim nBlockLen As Long
    nBlockLen = 512 \ 8
    
    lpData = cnvBytesFromHexStr("DEADBEEF")
    
    lpBlock = rsaEncodeMsg(nBlockLen, lpData, PKI_EME_PKCSV1_5)
    Debug.Print cnvHexStrFromBytes(lpBlock)
    lpDecoded = rsaDecodeMsg(lpBlock, PKI_EME_PKCSV1_5)
    Debug.Print "DECODED=" & cnvHexStrFromBytes(lpDecoded)
    
    lpBlock = rsaEncodeMsg(nBlockLen, lpData, PKI_EME_OAEP)
    Debug.Print cnvHexStrFromBytes(lpBlock)
    lpDecoded = rsaDecodeMsg(lpBlock, PKI_EME_OAEP)
    Debug.Print "DECODED=" & cnvHexStrFromBytes(lpDecoded)
    
    lpBlock = rsaEncodeMsg(nBlockLen, lpData, PKI_EMSIG_PKCSV1_5 Or PKI_HASH_SHA256)
    Debug.Print cnvHexStrFromBytes(lpBlock)
    lpDecoded = rsaDecodeMsg(lpBlock, PKI_EMSIG_PKCSV1_5)
    Debug.Print "DECODED=" & cnvHexStrFromBytes(lpDecoded)
    
    Debug.Print "DIGEST =" & hashHexFromBytes(lpData, PKI_HASH_SHA256)
    

End Sub

Public Sub V_Test_RSA_Encrypt()
    Debug.Print "Testing RSA_Encrypt code ..."
    Dim strPriKeyFile As String
    Dim strPubKeyFile As String
    Dim abMsg() As Byte
    Dim nMsgLen As Long
    Dim abEnc() As Byte
    Dim nEncLen As Long
    Dim abDec() As Byte
    Dim nDecLen As Long
    Dim strOkHex As String
    
    ' RSAES-OAEP Encryption Example 1.1 from `oaep-vect.txt` in `pkcs-1v2-1-vec.zip`
    ' RSA key file 1024-bit
    strPubKeyFile = "rsa-oaep-1.pub"
    strPriKeyFile = "rsa-oaep-1.p8"
    
    ' Message to be encrypted:
    abMsg = cnvBytesFromHexStr("6628194e12073db03ba94cda9ef9532397d50dba79b987004afefe34")
    nMsgLen = UBound(abMsg) + 1
    Debug.Print "MSG=" & cnvHexStrFromBytes(abMsg)
    
    ' 1. Encrypt using RSA-OAEP but set seed to be a fixed value to compare with test vector
    nEncLen = RSA_Encrypt(0, 0, abMsg(0), nMsgLen, strPubKeyFile, "seed=18b776ea21069d69776a33e96bad48e1dda0a5ef", PKI_EME_OAEP)
    Debug.Print "RSA_Encrypt() returns " & nEncLen & " (expecting 128 = 1024 bits)"
    ' Allocate memory for byte array
    ReDim abEnc(nEncLen - 1)
    ' Do the business - this should always give the same result
    nEncLen = RSA_Encrypt(abEnc(0), nEncLen, abMsg(0), nMsgLen, strPubKeyFile, "seed=18b776ea21069d69776a33e96bad48e1dda0a5ef", PKI_EME_OAEP)
    Debug.Print "ENC=" & cnvHexStrFromBytes(abEnc)
    
    ' Known answer from test vector
    strOkHex = "354fe67b4a126d5d35fe36c777791a3f7ba13def484e2d3908aff722fad468fb21696de95d0be911c2d3174f8afcc201035f7b6d8e69402de5451618c21a535fa9d7bfc5b8dd9fc243f8cf927db31322d6e881eaa91a996170e657a05a266426d98c88003f8477c1227094a0d9fa1e8c4024309ce1ecccb5210035d47ac72e8a"
    Debug.Print "OK =" & strOkHex
    
    ' 2. Decrypt - the private key is unencrypted with no password
    nDecLen = RSA_Decrypt(0, 0, abEnc(0), nEncLen, strPriKeyFile, "", "", PKI_EME_OAEP)
    Debug.Print "RSA_Decrypt() returns " & nDecLen
    ' Allocate memory for byte array
    ReDim abDec(nDecLen - 1)
    ' Decrypt
    nDecLen = RSA_Decrypt(abDec(0), nDecLen, abEnc(0), nEncLen, strPriKeyFile, "", "", PKI_EME_OAEP)
    Debug.Print "DEC=" & cnvHexStrFromBytes(abDec)
    
    ' 3. Encrypt using RSA-OAEP using SHA-256
    nEncLen = RSA_Encrypt(0, 0, abMsg(0), nMsgLen, strPubKeyFile, "", PKI_EME_OAEP + PKI_HASH_SHA256)
    Debug.Print "RSA_Encrypt() returns " & nEncLen & " (expecting 128 = 1024 bits)"
    ' Allocate memory for byte array
    ReDim abEnc(nEncLen - 1)
    ' Do the business - this will be different each time
    nEncLen = RSA_Encrypt(abEnc(0), nEncLen, abMsg(0), nMsgLen, strPubKeyFile, "", PKI_EME_OAEP + PKI_HASH_SHA256)
    Debug.Print "ENC=" & cnvHexStrFromBytes(abEnc)
    
    ' 4. Decrypt - we must specify the hash function used to encrypt
    nDecLen = RSA_Decrypt(0, 0, abEnc(0), nEncLen, strPriKeyFile, "", "", PKI_EME_OAEP + PKI_HASH_SHA256)
    Debug.Print "RSA_Decrypt() returns " & nDecLen
    ' Allocate memory for byte array
    ReDim abDec(nDecLen - 1)
    ' Decrypt
    nDecLen = RSA_Decrypt(abDec(0), nDecLen, abEnc(0), nEncLen, strPriKeyFile, "", "", PKI_EME_OAEP + PKI_HASH_SHA256)
    Debug.Print "DEC=" & cnvHexStrFromBytes(abDec)

End Sub

Public Sub V_Test_RSA_Encrypt2()
    Debug.Print "Testing RSA_Encrypt vbacode ..."
    Dim strPubKeyFile As String
    Dim lpMsg() As Byte
    Dim lpEnc() As Byte
    Dim strPriKeyFile As String
    Dim lpDec() As Byte
    
    ' Message to be encrypted:
    lpMsg = cnvBytesFromHexStr("6628194e12073db03ba94cda9ef9532397d50dba79b987004afefe34")
    Debug.Print "MSG=" & cnvHexStrFromBytes(lpMsg)
    
    ' Use RSA-OEAP with SHA-256
    strPubKeyFile = "rsa-oaep-1.pub"
    lpEnc = rsaEncrypt(lpMsg, strPubKeyFile, PKI_EME_OAEP + PKI_HASH_SHA256)
    ' NB different each time...
    Debug.Print "ENC=" & cnvHexStrFromBytes(lpEnc)
    strPriKeyFile = "rsa-oaep-1.p8"
    lpDec = rsaDecrypt(lpEnc, strPriKeyFile, "", PKI_EME_OAEP + PKI_HASH_SHA256)
    Debug.Print "DEC=" & cnvHexStrFromBytes(lpDec)
    
    strPubKeyFile = "rsa-oaep-1.pub"
    ' Set seed to fixed value for debugging....
    lpEnc = rsaEncrypt(lpMsg, strPubKeyFile, PKI_EME_OAEP, "seed=18b776ea21069d69776a33e96bad48e1dda0a5ef")
    Debug.Print "ENC=" & cnvHexStrFromBytes(lpEnc)
    Debug.Print "OK =354fe67b4a126d5d35fe36c777791a3f7ba13def484e2d3908aff722fad468fb" _
        & "21696de95d0be911c2d3174f8afcc201035f7b6d8e69402de5451618c21a535f" _
        & "a9d7bfc5b8dd9fc243f8cf927db31322d6e881eaa91a996170e657a05a266426" _
        & "d98c88003f8477c1227094a0d9fa1e8c4024309ce1ecccb5210035d47ac72e8a"
    ' Decrypt
    strPriKeyFile = "rsa-oaep-1.p8"
    lpDec = rsaDecrypt(lpEnc, strPriKeyFile, "", PKI_EME_OAEP)
    Debug.Print "DEC=" & cnvHexStrFromBytes(lpDec)

End Sub

Public Sub V_Test_RSA_FromXMLString()
    Debug.Print "Testing RSA_FromXMLString code ..."
        Dim strInternalKey As String
        Dim strXML As String
        Dim nLen As Long
        Dim nRet As Long
        
        strXML = "<RSAKeyValue>" _
    & "<Modulus>CmZ5HcaYgWjeerd0Gbt/sMABxicQJwB1FClC4ZqNjFH" _
    & "QU7PjeCod5dxa9OvplGgXARSh3+Z83Jqa9V1lViC7qw==</Modulus>" _
    & "<Exponent>AQAB</Exponent>" _
    & "</RSAKeyValue>"
    
        nLen = RSA_FromXMLString("", 0, strXML, 0)
        If nLen <= 0 Then
            MsgBox ("Error: " & nLen)
            Exit Sub
        End If
        strInternalKey = String(nLen, " ")
        nLen = RSA_FromXMLString(strInternalKey, Len(strInternalKey), strXML, 0)
        strInternalKey = Left(strInternalKey, nLen)
        
        Debug.Print "INTKEY=" & strInternalKey
        
        nRet = RSA_CheckKey(strInternalKey, 0)
        Debug.Print "RSA_CheckKey returns " & nRet

End Sub

Public Sub V_Test_RSA_FromXMLString2()
    Debug.Print "Testing RSA_FromXMLString code ..."
        Dim strInternalKey As String
        Dim strXML As String
        Dim nLen As Long
        Dim nRet As Long
        
        strXML = "<RSAKeyValue>" _
        & "<Modulus EncodingType='hexBinary'>0A66791D" _
        & "C6988168DE7AB77419BB7FB0C001C627102700751429" _
        & "42E19A8D8C51D053B3E3782A1DE5DC5AF4EBE9946817" _
        & "0114A1DFE67CDC9A9AF55D655620BBAB</Modulus>" _
        & "<Exponent EncodingType='hexBinary'>010001</Exponent>" _
        & "</RSAKeyValue>"
    
        nLen = RSA_FromXMLString("", 0, strXML, 0)
        If nLen <= 0 Then
            MsgBox ("Error: " & nLen)
            Exit Sub
        End If
        strInternalKey = String(nLen, " ")
        nLen = RSA_FromXMLString(strInternalKey, Len(strInternalKey), strXML, 0)
        strInternalKey = Left(strInternalKey, nLen)
        
        Debug.Print "INTKEY=" & strInternalKey
        
        nRet = RSA_CheckKey(strInternalKey, 0)
        Debug.Print "RSA_CheckKey returns " & nRet

End Sub

Public Sub V_Test_RSA_FromXMLString3()
    Debug.Print "Testing RSA_FromXMLString vbacode ..."
    Dim strPrivateKey As String
    strPrivateKey = rsaReadPrivateKey("AlicePrivRSASign.p8e", "password")
    Debug.Print rsaToXMLString(strPrivateKey, 0)
    Debug.Print rsaToXMLString(strPrivateKey, PKI_XML_EXCLPRIVATE Or PKI_XML_HEXBINARY)
    Debug.Print rsaToXMLStringEx(strPrivateKey, "ds", PKI_XML_EXCLPRIVATE)
    ' Now derive internal private key string from XML
    Dim strXML As String
    Dim strKey As String
    strXML = rsaToXMLString(strPrivateKey)
    strKey = rsaFromXMLString(strXML)
    Debug.Print "Key length = " & RSA_KeyBits(strKey) & " bits"
End Sub

Public Sub V_Test_RSA_GetPublicKeyFromCert()
    Debug.Print "Testing RSA_GetPublicKeyFromCert code ..."
    Dim strCertFile As String
    Dim strKeyFile As String
    Dim strPublicKey As String
    Dim nChars As Long
    Dim nRet As Long
    
    strCertFile = "AliceRSASignByCarl.cer"
    ' First find out the length of string we need
    nChars = RSA_GetPublicKeyFromCert(vbNullString, 0, strCertFile, 0)
    Debug.Print "RSA_GetPublicKeyFromCert returns " & nChars & " (expecting +ve)"
    If nChars <= 0 Then
        Debug.Print "ERROR: " & pkiErrorLookup(nChars)
        Exit Sub
    End If
    ' Pre-dimension the string to receive data - IMPORTANT
    strPublicKey = String(nChars, " ")
    ' Read in the Public Key in our "internal" format
    nRet = RSA_GetPublicKeyFromCert(strPublicKey, nChars, strCertFile, 0)
    Debug.Print "Public key is " & RSA_KeyBits(strPublicKey) & " bits long"
    
    ' Now save as a PKCS#1 public key file
    strKeyFile = "AlicePubRSA.pub"
    nRet = RSA_SavePublicKey(strKeyFile, strPublicKey, 0)
    Debug.Print "RSA_SavePublicKey returns " & nRet
    If nRet = 0 Then
        Debug.Print "Saved as public key file '" & strKeyFile & "'"
    Else
        Debug.Print "ERROR: " & pkiErrorLookup(nRet)
    End If

End Sub

Public Sub V_Test_RSA_KeyMatch()
    Debug.Print "Testing RSA_KeyMatch code ..."
    Dim strCertFile As String
    Dim strKeyFile As String
    Dim strPassword As String
    Dim strPublicKey As String
    Dim strPrivateKey As String
    Dim nRet As Long
    
    ' Input files
    strCertFile = "AAA010101AAAsd.cer"
    strKeyFile = "AAA010101AAA_0408021316S.key"
    ' Test password - CAUTION: DO NOT hardcode production passwords!
    strPassword = "Empresa1"
    
    ' Read in private key from encrypted .key file
    strPrivateKey = rsaReadPrivateKey(strKeyFile, strPassword)
    If Len(strPrivateKey) > 0 Then
        Debug.Print "Private key is " & RSA_KeyBits(strPrivateKey) & " bits"
    Else
        Debug.Print "ERROR: Cannot read private key file."
        Exit Sub
    End If
    
    ' Clean up password as we are done with it
    strPassword = wipeString(strPassword)
    
    ' Read in public key from certificate
    strPublicKey = rsaGetPublicKeyFromCert(strCertFile)
    If Len(strPublicKey) > 0 Then
        Debug.Print "Public key is " & RSA_KeyBits(strPublicKey) & " bits"
    Else
        Debug.Print "ERROR: Cannot read certificate file."
        Exit Sub
    End If
    
    ' See if the two key strings match
    nRet = RSA_KeyMatch(strPrivateKey, strPublicKey)
    If nRet = 0 Then
        Debug.Print "OK, key strings match."
    Else
        Debug.Print "FAILED: key strings do not match."
    End If
    
    ' Clean up private key string
    strPrivateKey = wipeString(strPrivateKey)

End Sub

Public Sub V_Test_RSA_KeyValue()
    Debug.Print "Testing RSA_KeyValue code ..."
    Dim nChars As Long
    Dim strKeyString As String
    Dim strFieldName As String
    Dim strValue As String
    
    ' Read in key to internal string
    strKeyString = rsaReadPublicKey("AliceRSASignByCarl.cer")
    
    strFieldName = "Modulus"
    nChars = RSA_KeyValue("", 0, strKeyString, strFieldName, 0)
    If (nChars < 0) Then
        Debug.Print "ERROR: " & pkiErrorLookup(nChars)
        Exit Sub
    End If
    ' Dimension output
    strValue = String(nChars, " ")
    nChars = RSA_KeyValue(strValue, nChars, strKeyString, strFieldName, 0)
    Debug.Print strFieldName & "=" & strValue
    
    strFieldName = "Exponent"
    nChars = RSA_KeyValue("", 0, strKeyString, strFieldName, 0)
    If (nChars < 0) Then
        Debug.Print "ERROR: " & pkiErrorLookup(nChars)
        Exit Sub
    End If
    ' Dimension output
    strValue = String(nChars, " ")
    nChars = RSA_KeyValue(strValue, nChars, strKeyString, strFieldName, 0)
    Debug.Print strFieldName & "=" & strValue

End Sub

Public Sub V_Test_RSA_KeyValue2()
    Debug.Print "Testing RSA_KeyValue vbacode ..."
    Dim strKeyString As String
    Dim strFieldName As String
    Dim strValue As String
    
    strKeyString = rsaReadPublicKey("AliceRSASignByCarl.cer")
    strFieldName = "Modulus"
    strValue = rsaKeyValue(strKeyString, strFieldName)
    Debug.Print strFieldName & "=" & strValue
    strFieldName = "Exponent"
    strValue = rsaKeyValue(strKeyString, strFieldName)
    Debug.Print strFieldName & "=" & strValue
End Sub

Public Sub V_Test_RSA_MakeKeys()
    Debug.Print "Testing RSA_MakeKeys code ..."
    Dim nRet As Long
    Dim sPublicKeyFile As String
    Dim sPrivateKeyFile As String
    Dim sPassword As String
    sPublicKeyFile = "mykey.pub"
    sPrivateKeyFile = "mykey.p8e"
    sPassword = "password"
    ' Create a new pair of RSA keys saved as BER-encoded files
    Debug.Print "About to create a new RSA key pair..."
    nRet = RSA_MakeKeys(sPublicKeyFile, sPrivateKeyFile, 512, _
        PKI_RSAEXP_EQ_3, 50, 1000, sPassword, "", 0, 0)
    Debug.Print "RSA_MakeKeys returns " & nRet & " (expected 0)"

End Sub

Public Sub V_Test_RSA_MakeKeysXtd2()
    Debug.Print "Testing RSA_MakeKeysXtd vbacode ..."
    Dim r As Long
    ' Create a 2048-bit RSA key pair using defaults
    r = rsaMakeKeys("myrsa2048.pub", "myrsa2048.p8e", "password", 2048)
    ' Same but using stronger security and in PEM format
    r = rsaMakeKeys("myrsa2048ex.pub", "myrsa2048ex.p8e", "password1", 2048, , "count=6000;prf=hmacWithSHA256", PKI_PBE_PBKDF2_AES128 Or PKI_KEY_FORMAT_PEM)

End Sub

Public Sub V_Test_RSA_PublicKeyFromPrivate()
    Debug.Print "Testing RSA_PublicKeyFromPrivate code ..."
    Dim strPriKeyFile As String
    Dim strPrivateKey As String
    Dim strPublicKey As String
    Dim nChars As Long
    Dim nCode As Long
    Dim nRet As Long
    
    ' Read private key from encrypted private key file into internal string form
    strPriKeyFile = "BobPrivRSAEncrypt.p8e"
    strPrivateKey = rsaReadPrivateKey(strPriKeyFile, "password")
    If Len(strPrivateKey) = 0 Then Exit Sub     'Catch error here
    ' Display some info about it
    Debug.Print "Private key length = " & RSA_KeyBits(strPrivateKey) & " bits"
    nCode = RSA_KeyHashCode(strPrivateKey)
    Debug.Print "KeyHashCode=" & Hex(nCode)
    nRet = RSA_CheckKey(strPrivateKey, 0)
    Debug.Print "RSA_CheckKey returns " & nRet & ": (PKI_VALID_PRIVATEKEY=" & PKI_VALID_PRIVATEKEY & ")"
    
    ' Convert to public key string
    nChars = RSA_PublicKeyFromPrivate("", 0, strPrivateKey, 0)
    If nChars <= 0 Then Exit Sub    ' Catch error here
    strPublicKey = String(nChars, " ")
    nChars = RSA_PublicKeyFromPrivate(strPublicKey, Len(strPublicKey), strPrivateKey, 0)
     ' Display some info about it
    Debug.Print "Public key length = " & RSA_KeyBits(strPublicKey) & " bits"
    nCode = RSA_KeyHashCode(strPublicKey)
    Debug.Print "KeyHashCode=" & Hex(nCode)
    nRet = RSA_CheckKey(strPublicKey, 0)
    Debug.Print "RSA_CheckKey returns " & nRet & ": (PKI_VALID_PUBLICKEY=" & PKI_VALID_PUBLICKEY & ")"
    
    ' Clean up
    strPrivateKey = wipeString(strPrivateKey)

End Sub

Public Sub V_Test_RSA_PublicKeyFromPrivate2()
    Debug.Print "Testing RSA_PublicKeyFromPrivate vbacode ..."
    Dim strPrivateKey As String
    Dim strPublicKey As String
    ' Read in private key to internal string
    strPrivateKey = rsaReadPrivateKey("BobPrivRSAEncrypt.p8e", "password")
    Debug.Assert Len(strPrivateKey) > 0
    Debug.Print "Private key length = " & RSA_KeyBits(strPrivateKey) & " bits"
    Debug.Print "KeyHashCode=0x" & Hex(RSA_KeyHashCode(strPrivateKey))
    ' Convert to public key string
    strPublicKey = rsaPublicKeyFromPrivate(strPrivateKey)
    Debug.Print "Public key length = " & RSA_KeyBits(strPublicKey) & " bits"
    Debug.Print "KeyHashCode=0x" & Hex(RSA_KeyHashCode(strPublicKey))
End Sub

Public Sub V_Test_RSA_RawPrivate()
    Debug.Print "Testing RSA_RawPrivate code ..."
    Dim strEPKFile As String
    Dim strPubFile As String
    Dim strPassword As String
    Dim strPublicKey As String
    Dim strPrivateKey As String
    Dim nRet As Long
    Dim strOutputFile As String
    Dim abData() As Byte
    Dim nDataLen As Long
    Dim sHexData As String
    
    strEPKFile = "rsa508.p8e"
    strPassword = "password"
    
    ' Read in the deciphered private key string
    strPrivateKey = rsaReadPrivateKey(strEPKFile, strPassword)
    If Len(strPrivateKey) = 0 Then
        MsgBox "Unable to retrieve private key"
        Exit Sub
    End If
    Debug.Print strPrivateKey
    
    ' Create some raw data to be RSA'd
    ' Ref: 3.2 Signing the CertificationRequestInfo encoding
    ' 64-octet EB in full:
    '00 01 ff ff ff ff ff ff ff ff ff ff ff ff ff ff
    'ff ff ff ff ff ff ff ff ff ff ff ff ff 00 30 20
    '30 0c 06 08 2a 86 48 86 f7 0d 02 02 05 00 04 10
    'dc a9 ec f1 c1 5c 1b d2 66 af f9 c8 79 93 65 cd
    
    sHexData = "0001ffffffffffffffffffffffffffff" & _
        "ffffffffffffffffffffffffff003020" & _
        "300c06082a864886f70d020205000410" & _
        "dca9ecf1c15c1bd266aff9c8799365cd"
    
    abData = cnvBytesFromHexStr(sHexData)
    nDataLen = UBound(abData) - LBound(abData) + 1
    Debug.Print "Input:  " & cnvHexStrFromBytes(abData)
    
    ' Now we have our data in a byte array and
    ' our private key in string format,
    ' we are ready to do a "raw" operation
    nRet = RSA_RawPrivate(abData(0), nDataLen, strPrivateKey, 0)
    Debug.Print "RSA_RawPrivate returns " & nRet
    If nRet <> 0 Then
        Debug.Print pkiGetLastError()
    Else
        ' Display our results in hex format
        Debug.Print "Output: " & cnvHexStrFromBytes(abData)
    End If
    
    ' Get the corresponding Public Key, also in a file
    strPubFile = "rsa508.pub"
    strPublicKey = rsaReadPublicKey(strPubFile)
    Debug.Print strPublicKey
    
    ' Do a "raw" encryption with the public key
    nRet = RSA_RawPublic(abData(0), nDataLen, strPublicKey, 0)
    Debug.Print "RSA_RawPublic returns " & nRet
    If nRet <> 0 Then
        Debug.Print pkiGetLastError()
    Else
        ' Display our results in hex format
        Debug.Print "Decrypt:" & cnvHexStrFromBytes(abData)
    End If

End Sub

Public Sub V_Test_RSA_RawPrivate2()
    Debug.Print "Testing RSA_RawPrivate vbacode ..."
    Dim strPrivateKey As String
    Dim pt() As Byte
    Dim ct() As Byte
    strPrivateKey = rsaReadPrivateKey("rsa508.p8e", "password")
    Debug.Assert Len(strPrivateKey) > 0
    pt = cnvBytesFromHexStr("0001ffffffffffffffffffffffffffff" & _
        "ffffffffffffffffffffffffff003020" & _
        "300c06082a864886f70d020205000410" & _
        "dca9ecf1c15c1bd266aff9c8799365cd")
    ct = rsaRawPrivate(pt, strPrivateKey)
    Debug.Print "CT=" & cnvHexStrFromBytes(ct)
    
    Dim strPublicKey As String
    Dim dt() As Byte
    strPublicKey = rsaReadPublicKey("Rsa508.pub")
    Debug.Assert Len(strPublicKey) > 0
    dt = rsaRawPublic(ct, strPublicKey)
    Debug.Print "DT=" & cnvHexStrFromBytes(dt)
End Sub

Public Sub V_Test_RSA_RawPublic()
    Debug.Print "Testing RSA_RawPublic code ..."
    Dim sEncDataHex As String
    Dim abData() As Byte
    Dim nDataLen As Long
    Dim strCertFile As String
    Dim nKeyLen As Long
    Dim strPublicKey As String
    Dim nRet As Long
    
    ' Cut and paste from DUMPASN1 output
    sEncDataHex = "2F 23 82 D2 F3 09 5F B8 0C 58 EB 4E" & _
        "9D BF 89 9A 81 E5 75 C4 91 3D D3 D0" & _
        "D5 7B B6 D5 FE 94 A1 8A AC E3 C4 84" & _
        "F5 CD 60 4E 27 95 F6 CF 00 86 76 75" & _
        "3F 2B F0 E7 D4 02 67 A7 F5 C7 8D 16" & _
        "04 A5 B3 B5 E7 D9 32 F0 24 EF E7 20" & _
        "44 D5 9F 07 C5 53 24 FA CE 01 1D 0F" & _
        "17 13 A7 2A 95 9D 2B E4 03 95 14 0B" & _
        "E9 39 0D BA CE 6E 9C 9E 0C E8 98 E6" & _
        "55 13 D4 68 6F D0 07 D7 A2 B1 62 4C" & _
        "E3 8F AF FD E0 D5 5D C7"
    
    ' Convert to bytes
    abData = cnvBytesFromHexStr(sEncDataHex)
    ' Check
    Debug.Print cnvHexStrFromBytes(abData)
    
    strCertFile = "AliceRSASignByCarl.cer"
    ' Read in PublicKey as base64 string - pre-dimension first
    nKeyLen = RSA_GetPublicKeyFromCert("", 0, strCertFile, 0)
    Debug.Print "KeyLen = " & nKeyLen
    If nKeyLen <= 0 Then
        Debug.Print pkiGetLastError()
        MsgBox "Unable to retrieve private key"
        Exit Sub
    End If
    ' Pre-dimension the string to receive data
    strPublicKey = String(nKeyLen, " ")
    ' Read in the Key
    nRet = RSA_GetPublicKeyFromCert(strPublicKey, nKeyLen, strCertFile, 0)
    Debug.Print "PubKey= " & strPublicKey
    
    ' Verify using the public key
    nDataLen = UBound(abData) + 1
    Debug.Print "Input:  " & cnvHexStrFromBytes(abData)
    nRet = RSA_RawPublic(abData(0), nDataLen, strPublicKey, 0)
    Debug.Print "Output: " & cnvHexStrFromBytes(abData)

End Sub

Public Sub V_Test_RSA_RawPublic2()
    Debug.Print "Testing RSA_RawPublic vbacode ..."
    Dim strPrivateKey As String
    Dim pt() As Byte
    Dim ct() As Byte
    strPrivateKey = rsaReadPrivateKey("rsa508.p8e", "password")
    Debug.Assert Len(strPrivateKey) > 0
    pt = cnvBytesFromHexStr("0001ffffffffffffffffffffffffffff" & _
        "ffffffffffffffffffffffffff003020" & _
        "300c06082a864886f70d020205000410" & _
        "dca9ecf1c15c1bd266aff9c8799365cd")
    ct = rsaRawPrivate(pt, strPrivateKey)
    Debug.Print "CT=" & cnvHexStrFromBytes(ct)
    
    Dim strPublicKey As String
    Dim dt() As Byte
    strPublicKey = rsaReadPublicKey("Rsa508.pub")
    Debug.Assert Len(strPublicKey) > 0
    dt = rsaRawPublic(ct, strPublicKey)
    Debug.Print "DT=" & cnvHexStrFromBytes(dt)
End Sub

Public Sub V_Test_RSA_ReadAnyPrivateKey()
    Debug.Print "Testing RSA_ReadAnyPrivateKey vbacode ..."
    Dim strIntKey As String
    
    strIntKey = rsaReadAnyPrivateKey("AlicePrivRSASign.p8e", "password")
    Debug.Print strIntKey
    Debug.Print "KeyHashCode=0x" & Hex(RSA_KeyHashCode(strIntKey))
    ' Unencrypted key
    strIntKey = rsaReadAnyPrivateKey("AlicePrivRSASign.pri", "")
    Debug.Print strIntKey
    Debug.Print "KeyHashCode=0x" & Hex(RSA_KeyHashCode(strIntKey))
    ' Key in XML form
    strIntKey = rsaReadAnyPrivateKey("alice-pri.xml", "")
    Debug.Print strIntKey
    Debug.Print "KeyHashCode=0x" & Hex(RSA_KeyHashCode(strIntKey))

End Sub

Public Sub V_Test_RSA_ReadAnyPublicKey()
    Debug.Print "Testing RSA_ReadAnyPublicKey code ..."
    Dim strJson As String
    Dim strPublicKey As String
    Dim nChars As Long
    
    ' RSA public key as a JSON string
    ' Ref: RFC 7517 JSON Web Key (JWK) Appendix A.1
    ' NB quotation marks (") inside a VBA string are escaped as "".
    strJson = "{""kty"":""RSA""," & _
        """n"": ""0vx7agoebGcQSuuPiLJXZptN9nndrQmbXEps2aiAFbWhM78LhWx" & _
        "4cbbfAAtVT86zwu1RK7aPFFxuhDR1L6tSoc_BJECPebWKRXjBZCiFV4n3oknjhMs" & _
        "tn64tZ_2W-5JsGY4Hc5n9yBXArwl93lqt7_RN5w6Cf0h4QyQ5v-65YGjQR0_FDW2" & _
        "QvzqY368QQMicAtaSqzs8KJZgnYb9c7d0zgdAZHzu6qMQvRL5hajrn1n91CbOpbI" & _
        "SD08qNLyrdkt-bFTWhAI4vMQFh6WeZu0fM4lFd2NcRwr3XPksINHaQ-G_xBniIqb" & _
        "w0Ls1jF44-csFCur-kEgU8awapJzKnqDKgw""," & _
        """e"":""AQAB""," & _
        """alg"":""RS256""," & _
        """kid"":""2011-04-29""}"
    
    Debug.Print strJson
    ' Read in the public key as an internal string
    ' How many characters?
    nChars = RSA_ReadAnyPublicKey(ByVal 0&, 0, strJson, 0)
    Debug.Print "RSA_ReadAnyPublicKey returns " & nChars
    strPublicKey = String(nChars, " ")
    nChars = RSA_ReadAnyPublicKey(strPublicKey, nChars, strJson, 0)
    ' Examine the key's properties
    Debug.Print "RSA key size = " & RSA_KeyBits(strPublicKey) & " bits"
    Debug.Print "Hash code = 0x" & Hex(RSA_KeyHashCode(strPublicKey))

End Sub

Public Sub V_Test_RSA_ReadAnyPublicKey2()
    Debug.Print "Testing RSA_ReadAnyPublicKey vbacode ..."
    Dim strIntKey As String
    
    strIntKey = rsaReadAnyPublicKey("AlicePubRSA.pub")
    Debug.Print strIntKey
    Debug.Print "KeyHashCode=0x" & Hex(RSA_KeyHashCode(strIntKey))
    ' X.509 certificate
    strIntKey = rsaReadAnyPublicKey("AliceRSASignByCarl.cer")
    Debug.Print strIntKey
    Debug.Print "KeyHashCode=0x" & Hex(RSA_KeyHashCode(strIntKey))
    ' Key in XML form
    strIntKey = rsaReadAnyPublicKey("alice-pub.xml")
    Debug.Print strIntKey
    Debug.Print "KeyHashCode=0x" & Hex(RSA_KeyHashCode(strIntKey))

End Sub

Public Sub V_Test_RSA_ReadPrivateKeyFromPFX()
    Debug.Print "Testing RSA_ReadPrivateKeyFromPFX code ..."
    Dim strPfxFile As String
    Dim strPrivateKey As String
    Dim strPassword As String
    Dim nChars As Long
    Dim nCode As Long
    Dim nRet As Long
    
    strPfxFile = "bob.pfx"
    strPassword = "password"
    
    ' Read private key from PFX file into internal string form
    nChars = RSA_ReadPrivateKeyFromPFX("", 0, strPfxFile, strPassword, 0)
    If nChars <= 0 Then Exit Sub    ' Catch error here
    strPrivateKey = String(nChars, " ")
    nChars = RSA_ReadPrivateKeyFromPFX(strPrivateKey, Len(strPrivateKey), strPfxFile, strPassword, 0)
    
    ' Display some info about it
    Debug.Print "Private key length = " & RSA_KeyBits(strPrivateKey) & " bits"
    nCode = RSA_KeyHashCode(strPrivateKey)
    Debug.Print "KeyHashCode=" & Hex(nCode)
    nRet = RSA_CheckKey(strPrivateKey, 0)
    Debug.Print "RSA_CheckKey returns " & nRet & ": (PKI_VALID_PRIVATEKEY=" & PKI_VALID_PRIVATEKEY & ")"
    
    ' Clean up
    strPrivateKey = wipeString(strPrivateKey)
    strPassword = wipeString(strPassword)

End Sub

Public Sub V_Test_RSA_ReadPrivateKeyInfo()
    Debug.Print "Testing RSA_ReadPrivateKeyInfo code ..."
    Dim strPRIFile As String
    Dim strEPKFile As String
    Dim strPrivateKey As String
    Dim strPK1 As String
    Dim nKeyLen As String
    Dim nRet As Long
    
    ' Read in Bob's unencrypted PrivateKeyInfo data
    strPRIFile = "BobPrivRSAEncrypt.pri"
    nKeyLen = RSA_ReadPrivateKeyInfo("", 0, strPRIFile, 0)
    If nKeyLen <= 0 Then
        MsgBox "Failed to read Private Key file"
        Exit Sub
    End If
    strPrivateKey = String(nKeyLen, " ")
    nRet = RSA_ReadPrivateKeyInfo(strPrivateKey, nKeyLen, strPRIFile, 0)
    If nRet <= 0 Then
        MsgBox "Failed to read Private Key file"
        Exit Sub
    End If
    ' Now we save it with a password
    strEPKFile = "BobPrivRSAEncrypt.p8e"
    nRet = RSA_SaveEncPrivateKey(strEPKFile, strPrivateKey, 1000, "password", 0)
    Debug.Print "RSA_SaveEncPrivateKey returns " & nRet
    
    ' Check we can read it
    strPK1 = rsaReadPrivateKey(strEPKFile, "password")
    
    ' Sneak a look at the two key strings.
    ' CAUTION: _Never_ print these in a production system!
    Debug.Print strPK1
    Debug.Print strPrivateKey
    
    ' To compare these strings, use the RSA_KeyHashCode function
    Debug.Print Hex(RSA_KeyHashCode(strPK1))
    Debug.Print Hex(RSA_KeyHashCode(strPrivateKey))
    If RSA_KeyHashCode(strPK1) = RSA_KeyHashCode(strPrivateKey) Then
        Debug.Print "Key string values match."
    Else
        Debug.Print "ERROR: key strings do not match."
    End If

End Sub

Public Sub V_Test_RSA_SaveEncPrivateKey()
    Debug.Print "Testing RSA_SaveEncPrivateKey code ..."
    Dim strPRIFile As String
    Dim strEPKFile As String
    Dim strPrivateKey As String
    Dim strPK1 As String
    Dim nChars As String
    Dim nRet As Long
    
    strPRIFile = "CarlPrivRSASign.pri"
    
    ' Read in Carl's unencrypted PrivateKeyInfo data
    nChars = RSA_ReadPrivateKeyInfo("", 0, strPRIFile, 0)
    If nChars <= 0 Then
        MsgBox "Failed to read Private Key file"
        Exit Sub
    End If
    ' Dimension the string to receive it - IMPORTANT
    strPrivateKey = String(nChars, " ")
    ' Read in as an "internal" key string
    nRet = RSA_ReadPrivateKeyInfo(strPrivateKey, nChars, strPRIFile, 0)
    If nRet <= 0 Then
        MsgBox "Failed to read Private Key file"
        Exit Sub
    End If
    Debug.Print "Private key length is " & RSA_KeyBits(strPrivateKey) & " bits"
    
    ' Now save it in PKCS#8 encrypted form with a password
    strEPKFile = "CarlPrivRSASign.p8e"
    nRet = RSA_SaveEncPrivateKey(strEPKFile, strPrivateKey, 1000, "password", 0)
    Debug.Print "RSA_SaveEncPrivateKey returns " & nRet & " (expected 0)"
    
    ' Check we can read it (note easier wrapper function)
    strPK1 = rsaReadPrivateKey(strEPKFile, "password")
    If Len(strPK1) > 0 Then
        Debug.Print "Encrypted private key is " & RSA_KeyBits(strPK1) & " bits"
    Else
        MsgBox "Unable to read encrypted private key"
    End If
    
    ' To compare these strings, use the RSA_KeyHashCode function
    Debug.Print "HashCode(original prikeyinfo) =" & Hex(RSA_KeyHashCode(strPrivateKey))
    Debug.Print "HashCode(encrypted prikeyinfo)=" & Hex(RSA_KeyHashCode(strPK1))
    If RSA_KeyHashCode(strPK1) = RSA_KeyHashCode(strPrivateKey) Then
        Debug.Print "OK, Key string values match."
    Else
        Debug.Print "ERROR: key strings do not match."
    End If

End Sub

Public Sub V_Test_RSA_SavePrivateKeyInfo()
    Debug.Print "Testing RSA_SavePrivateKeyInfo code ..."
        Dim strEPKFile As String
        Dim strPRIFile As String
        Dim strPEMFile As String
        Dim strPassword As String
        Dim strPrivateKey As String
        Dim nRet As Long
        
        strEPKFile = "rsa508.p8e"
        strPRIFile = "rsa508.pri"
        strPEMFile = "rsa508.pem"
        strPassword = "password"
        
        ' Read in the deciphered private key string
        strPrivateKey = rsaReadPrivateKey(strEPKFile, strPassword)
        If Len(strPrivateKey) = 0 Then
            MsgBox "Unable to retrieve private key"
            Exit Sub
        End If
        Debug.Print strPrivateKey
        
        ' Save as unencrypted PrivateKeyInfo file
        nRet = RSA_SavePrivateKeyInfo(strPRIFile, strPrivateKey, 0)
        Debug.Print "RSA_SavePrivateKeyInfo returns " & nRet
        
        ' Save as unencrypted PEM-format file
        nRet = RSA_SavePrivateKeyInfo(strPEMFile, strPrivateKey, PKI_KEY_FORMAT_PEM)
        Debug.Print "RSA_SavePrivateKeyInfo returns " & nRet
    

End Sub

Public Sub V_Test_RSA_ToXMLString()
    Debug.Print "Testing RSA_ToXMLString code ..."
        Dim strEPKFile As String
        Dim strPassword As String
        Dim strPrivateKey As String
        Dim strXML As String
        Dim nLen As Long
    
        strEPKFile = "AlicePrivRSASign.p8e"
        strPassword = "password"
        
        ' Read in the deciphered private key string in our internal format
        strPrivateKey = rsaReadPrivateKey(strEPKFile, strPassword)
        If Len(strPrivateKey) = 0 Then
            MsgBox "Unable to retrieve private key"
            Exit Sub
        End If
        Debug.Print "INTKEY=" & strPrivateKey
        
        ' Convert to XML
        nLen = RSA_ToXMLString("", 0, strPrivateKey, PKI_XML_RSAKEYVALUE)
        ' pre-dimension first
        strXML = String(nLen, " ")
        nLen = RSA_ToXMLString(strXML, Len(strXML), strPrivateKey, PKI_XML_RSAKEYVALUE)
        strXML = Left(strXML, nLen)
        Debug.Print "XML=" & strXML

End Sub

Public Sub V_Test_RSA_ToXMLString2()
    Debug.Print "Testing RSA_ToXMLString vbacode ..."
    Dim strPrivateKey As String
    strPrivateKey = rsaReadPrivateKey("AlicePrivRSASign.p8e", "password")
    Debug.Print rsaToXMLString(strPrivateKey, 0)
    Debug.Print rsaToXMLString(strPrivateKey, PKI_XML_EXCLPRIVATE Or PKI_XML_HEXBINARY)
    Debug.Print rsaToXMLStringEx(strPrivateKey, "ds", PKI_XML_EXCLPRIVATE)
    ' Now derive internal private key string from XML
    Dim strXML As String
    Dim strKey As String
    strXML = rsaToXMLString(strPrivateKey)
    strKey = rsaFromXMLString(strXML)
    Debug.Print "Key length = " & RSA_KeyBits(strKey) & " bits"
End Sub

Public Sub V_Test_RSA_ToXMLStringEx()
    Debug.Print "Testing RSA_ToXMLStringEx vbacode ..."
    Dim strPrivateKey As String
    strPrivateKey = rsaReadPrivateKey("AlicePrivRSASign.p8e", "password")
    Debug.Print rsaToXMLString(strPrivateKey, 0)
    Debug.Print rsaToXMLString(strPrivateKey, PKI_XML_EXCLPRIVATE Or PKI_XML_HEXBINARY)
    Debug.Print rsaToXMLStringEx(strPrivateKey, "ds", PKI_XML_EXCLPRIVATE)
    ' Now derive internal private key string from XML
    Dim strXML As String
    Dim strKey As String
    strXML = rsaToXMLString(strPrivateKey)
    strKey = rsaFromXMLString(strXML)
    Debug.Print "Key length = " & RSA_KeyBits(strKey) & " bits"
End Sub

Public Sub V_Test_SIG_SignData()
    Debug.Print "Testing SIG_SignData code ..."
    Dim strSignature As String
    Dim nChars As Long
    Dim strData As String
    Dim abData() As Byte
    Dim nDataLen As Long
    Dim strKeyFile As String
    Dim strPassword As String
    Dim strAlgName As String
    
    ' 1) Input data = three-character ASCII string "abc"
    strData = "abc"
    strKeyFile = "AlicePrivRSASign.p8e"
    strPassword = "password" ' CAUTION: do not hard-code passwords!
    strAlgName = "sha1WithRSAEncryption"
    
    ' Convert ASCII string to byte array
    abData = StrConv(strData, vbFromUnicode)
    nDataLen = Len(strData)
    ' Find required length of output string
    nChars = SIG_SignData("", 0, abData(0), nDataLen, strKeyFile, strPassword, _
      strAlgName, 0)
    Debug.Print "SIG_SignData returns " & nChars & " (expected >0)"
    ' Allocate memory for output string
    strSignature = String(nChars, " ")
    nChars = SIG_SignData(strSignature, Len(strSignature), abData(0), nDataLen, _
      strKeyFile, strPassword, strAlgName, 0)
    ' Output base64 signature value
    Debug.Print "SIG=" & strSignature
    
    ' 2) Use digest value instead of original data
    ' Convert known value of SHA-1("abc") in hex to an array of bytes
    abData = cnvBytesFromHexStr("a9993e364706816aba3e25717850c26c9cd0d89d")
    nDataLen = PKI_SHA1_BYTES
    ' Find required length of output string
    nChars = SIG_SignData("", 0, abData(0), nDataLen, strKeyFile, strPassword, _
      strAlgName, PKI_SIG_USEDIGEST)
    Debug.Print "SIG_SignData returns " & nChars & " (expected >0)"
    ' Allocate memory for output string
    strSignature = String(nChars, " ")
    nChars = SIG_SignData(strSignature, Len(strSignature), abData(0), nDataLen, _
      strKeyFile, strPassword, strAlgName, PKI_SIG_USEDIGEST)
    ' Output base64 signature value
    Debug.Print "SIG=" & strSignature

End Sub

Public Sub V_Test_SIG_SignData2()
    Debug.Print "Testing SIG_SignData code ..."
    Dim nChars As Long
    Dim nBits As Long
    Dim strIntKey As String
    Dim strHexKey As String
    Dim strCurveName As String
    Dim strSignature As String
    Dim strData As String
    Dim abData() As Byte
    Dim nDataLen As Long
    Dim strAlgName As String
    
    ' Ref: [RFC6979] "Deterministic Usage of the DSA and ECDSA"
    ' A.2.3.  ECDSA, 192 Bits (Prime Field)
      
    ' 1. READ IN PRIVATE KEY IN (HEX,CURVENAME) FORMAT
    strHexKey = "6FAB034934E4C0FC9AE67F5B5659A9D7D1FEFD187EE09FD4"
    strCurveName = "P-192"
    Debug.Print "KEYHEX: " & strHexKey
    Debug.Print "CURVE: " & strCurveName
    ' Find required length of internal key string
    nChars = ECC_ReadKeyByCurve("", 0, strHexKey, strCurveName, 0)
    Debug.Print "ECC_ReadKeyByCurve returns " & nChars & " (expected +ve)"
    ' Dimension the string to receive output
    strIntKey = String(nChars, " ")
    ' Read into internal key string
    nChars = ECC_ReadKeyByCurve(strIntKey, Len(strIntKey), strHexKey, strCurveName, 0)
    'Debug.Print "INTKEY: " & strIntKey
    ' Check we got the bitlength we expected
    nBits = ECC_QueryKey("", 0, strIntKey, "keyBits", 0)
    Debug.Print "NBITS=" & nBits
    
    ' 2. PREPARE INPUT DATA AS AN ARRAY OF BYTES
    strData = "test"
    strAlgName = "ecdsaWithSHA1"
    ' Convert ASCII string to byte array
    abData = StrConv(strData, vbFromUnicode)
    nDataLen = Len(strData)
      
    '3. SIGN IT USING DETERMINISTIC ALGORITHM FROM [RFC6979]
    ' Find required length of output string
    nChars = SIG_SignData("", 0, _
        abData(0), nDataLen, strIntKey, "", _
        strAlgName, PKI_SIG_DETERMINISTIC Or PKI_ENCODE_HEX)
    Debug.Print "SIG_SignData returns " & nChars & " (expected >0)"
    ' Allocate memory for output string
    strSignature = String(nChars, " ")
    nChars = SIG_SignData(strSignature, Len(strSignature), _
        abData(0), nDataLen, strIntKey, "", _
        strAlgName, PKI_SIG_DETERMINISTIC Or PKI_ENCODE_HEX)
    
    ' Output hex signature value
    Debug.Print "SIG=" & strSignature

End Sub

Public Sub V_Test_SIG_SignData3()
    Debug.Print "Testing SIG_SignData vbacode ..."
    Dim lpData() As Byte
    Dim strSig As String
    lpData = StrConv("abc", vbFromUnicode)
    strSig = sigSignData(lpData, "AlicePrivRSASign.p8e", "password", "sha1WithRSAEncryption")
    Debug.Print "SIG=" & strSig
    Debug.Print "OK =" & "YK1aePtKQDDsVCyJdM0V9VOE6DZVTO3Z ... AmHH6QIsDZ8R8="
End Sub

Public Sub V_Test_SIG_SignFile()
    Debug.Print "Testing SIG_SignFile code ..."
    Dim strSignature As String
    Dim strDataFile As String
    Dim strKeyFile As String
    Dim strPassword As String
    Dim nChars As Long
    Dim nOption As Long
    
    'Input data = file containing the three bytes 'a', 'b', 'c'
    strDataFile = "abc.txt"
    strKeyFile = "AlicePrivRSASign.p8e"
    strPassword = "password" ' CAUTION: do not hard-code passwords!
    nOption = PKI_SIG_SHA256RSA ' Use option instead of string
    
    ' Find required length of output string
    nChars = SIG_SignFile("", 0, strDataFile, strKeyFile, strPassword, "", nOption)
    Debug.Print "SIG_SignFile returns " & nChars & " (expected >0)"
    ' Allocate memory for output string
    strSignature = String(nChars, " ")
    nChars = SIG_SignFile(strSignature, Len(strSignature), strDataFile, strKeyFile, strPassword, "", nOption)
    ' Output base64 signature value
    Debug.Print "SIG=" & strSignature

End Sub

Public Sub V_Test_SIG_SignFile2()
    Debug.Print "Testing SIG_SignFile vbacode ..."
    Dim strSig As String
    strSig = sigSignFile("abc.txt", "AlicePrivRSASign.p8e", "password", "", PKI_SIG_SHA256RSA)
    Debug.Print "SIG=" & strSig
    Debug.Print "OK =" & "tLy6hJadL4w9JI/A/qLCG0V...peD1VHSzgu/qirjOaA="
End Sub

Public Sub V_Test_SIG_VerifyData()
    Debug.Print "Testing SIG_VerifyData code ..."
    Dim strSignature As String
    Dim strData As String
    Dim abData() As Byte
    Dim nDataLen As Long
    Dim strCertFile As String
    Dim strAlgName As String
    Dim nRet As Long
    
    ' Signature to be verified
    strSignature = _
    "YK1aePtKQDDsVCyJdM0V9VOE6DZVTO3ZoyLV9BNcYmep0glwxU5mUQcLAUTUOETImTIN2Pp4Gffr" & _
    "xqdxUoczLshnXBNhg7P4ofge+WlBgmcTCnVv27LHHZpmdEbjTg6tnPMb+2b4FvMZ0LfkMKXyiRVTmG4A" & _
    "NyAmHH6QIsDZ8R8="
    ' Data to be verified against signature = three-character ASCII string "abc"
    strData = "abc"
    strCertFile = "AliceRSASignByCarl.cer"
    strAlgName = "sha1WithRSAEncryption"
    ' Convert ASCII string to byte array
    abData = StrConv(strData, vbFromUnicode)
    nDataLen = Len(strData)
    ' Verify the signature...
    nRet = SIG_VerifyData(strSignature, abData(0), nDataLen, strCertFile, strAlgName, 0)
    Debug.Print "SIG_VerifyData returns " & nRet & " (expecting 0)"

End Sub

Public Sub V_Test_SIG_VerifyFile()
    Debug.Print "Testing SIG_VerifyFile code ..."
    Dim strSignature As String
    Dim strDataFile As String
    Dim strCertFile As String
    Dim strAlgName As String
    Dim nRet As Long
    
    ' Signature to be verified
    strSignature = _
    "tLy6hJadL4w9JI/A/qLCG0Vz1fWPIrPMWD8NGmA5wP7HHlUID54elztUYrpdm9RFeh0RCMJ618dw" & _
    "BpgIutuZg2qQ2i9uMUYB0DvZvkyeD6MqmtVa4ihgc9SLqhigKeP+KB7voEi7PH3hpEr9Wa3kn4mb" & _
    "PpeD1VHSzgu/qirjOaA="
    ' File to be verified against signature = three-character ASCII string "abc"
    strDataFile = "abc.txt"
    strCertFile = "AliceRSASignByCarl.cer"
    strAlgName = "sha256WithRSAEncryption"
    ' Verify the signature over the data in the file...
    nRet = SIG_VerifyFile(strSignature, strDataFile, strCertFile, strAlgName, 0)
    Debug.Print "SIG_VerifyFile returns " & nRet & " (expecting 0)"

End Sub

Public Sub V_Test_SMIME_Extract()
    Debug.Print "Testing SMIME_Extract code ..."
    nRet = SMIME_Extract("cmsalice2bob-extracted.p7m", "cmsalice2bob-smime-env.txt", 0)

End Sub

Public Sub V_Test_SMIME_Query()
    Debug.Print "Testing SMIME_Query code ..."
    Dim strQuery As String
    Dim strOutput As String
    Dim nRet As Long
    Dim strFileIn As String
    
    strFileIn = "cmsalice2bob-smime-env.txt"
    Debug.Print "FILE: " & strFileIn
    
    ' Make a buffer large enough to receive output
    strOutput = String(512, " ")
    
    strQuery = "content-type"
    nRet = SMIME_Query(strOutput, Len(strOutput), strFileIn, strQuery, 0)
    If nRet <= 0 Then Exit Sub  ' catch error
    Debug.Print strQuery & "=" & Left(strOutput, nRet)
    
    strQuery = "smime-type"
    nRet = SMIME_Query(strOutput, Len(strOutput), strFileIn, strQuery, 0)
    If nRet <= 0 Then Exit Sub  ' catch error
    Debug.Print strQuery & "=" & Left(strOutput, nRet)
    
    strQuery = "encoding"
    nRet = SMIME_Query(strOutput, Len(strOutput), strFileIn, strQuery, 0)
    If nRet <= 0 Then Exit Sub  ' catch error
    Debug.Print strQuery & "=" & Left(strOutput, nRet)
    
    strQuery = "filename"
    nRet = SMIME_Query(strOutput, Len(strOutput), strFileIn, strQuery, 0)
    If nRet <= 0 Then Exit Sub  ' catch error
    Debug.Print strQuery & "=" & Left(strOutput, nRet)

End Sub

Public Sub V_Test_SMIME_Query2()
    Debug.Print "Testing SMIME_Query vbacode ..."
    Dim strFileIn As String
    Dim strQuery As String
    
    strFileIn = "cmsalice2bob-smime-env.txt"
    Debug.Print "FILE: " & strFileIn
    strQuery = "content-type"
    Debug.Print strQuery & "=" & smimeQuery(strFileIn, strQuery, 0)
    strQuery = "smime-type"
    Debug.Print strQuery & "=" & smimeQuery(strFileIn, strQuery, 0)
    strQuery = "encoding"
    Debug.Print strQuery & "=" & smimeQuery(strFileIn, strQuery, 0)
    strQuery = "filename"
    Debug.Print strQuery & "=" & smimeQuery(strFileIn, strQuery, 0)
End Sub

Public Sub V_Test_SMIME_Wrap()
    Debug.Print "Testing SMIME_Wrap code ..."
    nRet = SMIME_Wrap("cmsalice2bob-smime-env.txt", "cmsalice2bob.p7m", "", 0)

End Sub

Public Sub V_Test_TDEA_B64Mode()
    Debug.Print "Testing TDEA_B64Mode code ..."
    Dim nRet As Long
    Dim sHexCorrect As String
    Dim sHexInput As String
    Dim sHexKey As String
    Dim sHexInitV As String
    Dim sOutput As String
    Dim sInput As String
    Dim sKey As String
    Dim sInitV As String
    Dim bEncrypt As Boolean
    Dim sCorrect As String
    
    ' Start with input in hex
    sHexInput = "5468697320736F6D652073616D706520636F6E74656E742E0808080808080808"
    '            T h i s _ s o m e _ s a m p e _ c o n t e n t . (padding 8 x 08)
    sHexKey = "737C791F25EAD0E04629254352F7DC6291E5CB26917ADA32"
    sHexInitV = "B36B6BFB6231084E"
    sHexCorrect = "d76fd1178fbd02f84231f5c1d2a2f74a4159482964f675248254223daf9af8e4"
    
    ' Convert to base64
    sInput = cnvB64StrFromBytes(cnvBytesFromHexStr(sHexInput))
    sKey = cnvB64StrFromBytes(cnvBytesFromHexStr(sHexKey))
    sInitV = cnvB64StrFromBytes(cnvBytesFromHexStr(sHexInitV))
    sCorrect = cnvB64StrFromBytes(cnvBytesFromHexStr(sHexCorrect))
    
    ' Set sOutput to be same length as sInput
    sOutput = String(Len(sInput), " ")
    
    Debug.Print "KY=" & sKey
    Debug.Print "PT=" & sInput
    Debug.Print "IV=" & sInitV
    nRet = TDEA_B64Mode(sOutput, sInput, sKey, ENCRYPT, "CBC", sInitV)
    Debug.Print "CT=" & sOutput & nRet
    Debug.Print "OK=" & sCorrect
    
    sInput = sOutput
    nRet = TDEA_B64Mode(sOutput, sInput, sKey, DECRYPT, "CBC", sInitV)
    Debug.Print "P'=" & sOutput & nRet

End Sub

Public Sub V_Test_TDEA_BytesMode()
    Debug.Print "Testing TDEA_BytesMode code ..."
    Dim nRet As Long
    Dim sOutput As String
    Dim sInput As String
    Dim sKey As String
    Dim sHexIV As String
    Dim sCorrect As String
    Dim nKeyLen As Long
    Dim nDataLen As Long
    Dim nIVLen As Long
    Dim aKey() As Byte
    Dim aResult() As Byte
    Dim aData() As Byte
    Dim aInitV() As Byte
    
    sKey = "0123456789abcdeffedcba987654321089abcdef01234567"
    sHexIV = "1234567890abcdef"
    sInput = "Now is the time for all "
    sCorrect = "204011f986e35647199e47af391620c5bb9a5bcfc86db0bb"
    
    ' Convert hex strings to byte arrays
    nKeyLen = Len(sKey) \ 2
    ReDim aKey(nKeyLen)
    Call CNV_BytesFromHexStr(aKey(0), nKeyLen, sKey)
    nIVLen = Len(sHexIV) \ 2
    ReDim aInitV(nIVLen)
    Call CNV_BytesFromHexStr(aInitV(0), nIVLen, sHexIV)
    
    ' Convert string to byte array and dimension aResult array
    aData() = StrConv(sInput, vbFromUnicode)
    nDataLen = UBound(aData) + 1
    ReDim aResult(nDataLen - 1)
    
    Debug.Print "KY=" & cnvHexStrFromBytes(aKey)
    Debug.Print "IV=" & cnvHexStrFromBytes(aInitV)
    Debug.Print "PT=" & "[" & sInput & "]"
    ' Encrypt in one-off process
    nRet = TDEA_BytesMode(aResult(0), aData(0), nDataLen, _
        aKey(0), ENCRYPT, "CBC", aInitV(0))
    Debug.Print "CT=" & cnvHexStrFromBytes(aResult) & nRet
    Debug.Print "OK=" & sCorrect
    
    ' Now decrypt back
    nRet = TDEA_BytesMode(aData(0), aResult(0), nDataLen, _
        aKey(0), DECRYPT, "cbc", aInitV(0))
    sOutput = StrConv(aData(), vbUnicode)
    Debug.Print "P'=" & "[" & sOutput & "]" & nRet

End Sub

Public Sub V_Test_TDEA_File()
    Debug.Print "Testing TDEA_File code ..."
        Const MY_PATH As String = ""
        Dim aKey() As Byte
        Dim strFileOut As String
        Dim strFileIn As String
        Dim strFileChk As String
        Dim nRet As Long
    
        ' Construct full path names to files
        strFileIn = MY_PATH & "hello.txt"
        strFileOut = MY_PATH & "hello.tdea.enc.dat"
        strFileChk = MY_PATH & "hello.tdea.chk.txt"
    
        ' Create the key as an array of bytes
        ' This creates an array of 24 bytes {&HFE, &HDC, ... &H10}
        aKey = cnvBytesFromHexStr("fedcba9876543210fedcba9876543210fedcba9876543210")
    
        ' Encrypt plaintext file to ciphertext
        ' Output file = 16-byte ciphertext file hello.enc
        nRet = TDEA_File(strFileOut, strFileIn, aKey(0), ENCRYPT, "ECB", 0)
        Debug.Print nRet
    
        ' Now decrypt it
        nRet = TDEA_File(strFileChk, strFileOut, aKey(0), DECRYPT, "ECB", 0)
        Debug.Print nRet

End Sub

Public Sub V_Test_TDEA_HexMode()
    Debug.Print "Testing TDEA_HexMode code ..."
    Dim nRet As Long
    Dim sOutput As String
    Dim sInput As String
    Dim sKey As String
    Dim sInitV As String
    Dim sCorrect As String
    
    sInput = "5468697320736F6D652073616D706520636F6E74656E742E0808080808080808"
    '         T h i s _ s o m e _ s a m p e _ c o n t e n t . (padding 8 x 08)
    sKey = "737C791F25EAD0E04629254352F7DC6291E5CB26917ADA32"
    sInitV = "B36B6BFB6231084E"
    sCorrect = "d76fd1178fbd02f84231f5c1d2a2f74a4159482964f675248254223daf9af8e4"
    ' Set sOutput to be same length as sInput
    sOutput = String(Len(sInput), " ")
    
    Debug.Print "KY=" & sKey
    Debug.Print "PT=" & sInput
    nRet = TDEA_HexMode(sOutput, sInput, sKey, ENCRYPT, "CBC", sInitV)
    Debug.Print "CT=" & sOutput & nRet
    Debug.Print "OK=" & sCorrect
    
    sInput = sOutput
    nRet = TDEA_HexMode(sOutput, sInput, sKey, DECRYPT, "CBC", sInitV)
    Debug.Print "P'=" & sOutput & nRet

End Sub

Public Sub V_Test_WIPE_Data()
    Debug.Print "Testing WIPE_Data code ..."
    Dim strData As String
    strData = "my deepest secrets"
    nRet = WIPE_String(strData, Len(strData))
    strData = ""

End Sub

Public Sub V_Test_WIPE_Data2()
    Debug.Print "Testing WIPE_Data vbacode ..."
    Dim strData As String
    strData = "my deepest secrets"
    strData = wipeString(strData)

End Sub

Public Sub V_Test_WIPE_Data3()
    Debug.Print "Testing WIPE_Data vbacode ..."
    Dim lpData() As Byte
    lpData = cnvBytesFromHexStr("DEADBEEF")
    Debug.Print "BEFORE: " & cnvHexStrFromBytes(lpData)
    Call wipeBytes(lpData)
    Debug.Print "AFTER: '" & cnvHexStrFromBytes(lpData) & "'"

End Sub

Public Sub V_Test_WIPE_File()
    Debug.Print "Testing WIPE_File code ..."
    nRet = WIPE_File("ToDelete.txt", 0)

End Sub

Public Sub V_Test_X509_CertExpiresOn()
    Debug.Print "Testing X509_CertExpiresOn code ..."
    Dim nRet As Long
    Dim strCertName As String
    Dim strDateTime As String * 32
     
    strCertName = "AliceRSASignByCarl.cer"  ' Change your dir to suit
    nRet = X509_CertIssuedOn(strCertName, strDateTime, Len(strDateTime), 0)
    Debug.Print "X509_CertIssuedOn returns " & nRet & " for " & strCertName & ": " & strDateTime
    nRet = X509_CertExpiresOn(strCertName, strDateTime, Len(strDateTime), 0)
    Debug.Print "X509_CertExpiresOn returns " & nRet & " for " & strCertName & ": " & strDateTime

End Sub

Public Sub V_Test_X509_CertIsValidNow()
    Debug.Print "Testing X509_CertIsValidNow code ..."
    Dim nRet As Long
    Dim strCertName As String
     
    strCertName = "myca.cer"
    nRet = X509_CertIsValidNow(strCertName, 0)
    Debug.Print "X509_CertIsValidNow returns " & nRet & " for " & strCertName

End Sub

Public Sub V_Test_X509_CertRequest()
    Debug.Print "Testing X509_CertRequest code ..."
    Dim nRet As Long
    nRet = X509_CertRequest("myreq.p10.txt", "mykey.p8e", _
      "CN=myuser;O=Test Org;C=AU;L=Sydney;S=NSW", "", "password", 0)
    If nRet <> 0 Then
      Debug.Print nRet & " " & pkiGetLastError()
    Else
      Debug.Print "Success"
    End If

End Sub

Public Sub V_Test_X509_CertRequest2()
    Debug.Print "Testing X509_CertRequest code ..."
    Dim nRet As Long
    nRet = X509_CertRequest("pkcs_ex_req.bin", "rsa508.p8e", _
      "C=US;O=Example Organization;CN=Test User 1", "", "password", _
      PKI_SIG_MD2RSA + PKI_X509_FORMAT_BIN + PKI_X509_REQ_KLUDGE)
    If nRet <> 0 Then
      Debug.Print nRet & " " & pkiGetLastError()
    Else
      Debug.Print "Success"
    End If

End Sub

Public Sub V_Test_X509_CertSerialNumber()
    Debug.Print "Testing X509_CertSerialNumber code ..."
    Dim nRet As Long
    Dim strCertName As String
    Dim strOutput As String * 64
     
    strCertName = "BobRSASignByCarl.cer"    ' Set dir to suit
    nRet = X509_CertSerialNumber(strCertName, strOutput, Len(strOutput), 0)
    Debug.Print "X509_CertSerialNumber returns " & nRet & " for " & strCertName & ": " & Left(strOutput, nRet)

End Sub

Public Sub V_Test_X509_CertSubjectName()
    Debug.Print "Testing X509_CertSubjectName code ..."
    Dim nRet As Long
    Dim nLen As Long
    Dim strCertName As String
    Dim strOutput As String
     
    strCertName = "dai.cer"
    nLen = X509_CertIssuerName(strCertName, "", 0, ";", 0)
    Debug.Print "X509_CertIssuerName returns " & nLen & " for " & strCertName
    strOutput = String(nLen, " ")
    nRet = X509_CertIssuerName(strCertName, strOutput, Len(strOutput), ";", 0)
    Debug.Print "[" & strOutput & "]"
    
    ' Example outputting in LDAP format
    nLen = X509_CertIssuerName(strCertName, "", 0, "", PKI_X509_LDAP)
    Debug.Print "X509_CertIssuerName(LDAP) returns " & nLen & " for " & strCertName
    strOutput = String(nLen, " ")
    nRet = X509_CertIssuerName(strCertName, strOutput, Len(strOutput), "", PKI_X509_LDAP)
    Debug.Print "[" & strOutput & "]"
    
    nLen = X509_CertSubjectName(strCertName, "", 0, ";", 0)
    Debug.Print "X509_CertSubjectName returns " & nLen & " for " & strCertName
    strOutput = String(nLen, " ")
    nRet = X509_CertSubjectName(strCertName, strOutput, Len(strOutput), ",", 0)
    Debug.Print "[" & strOutput & "]"
    
    ' Example outputting in LDAP format
    nLen = X509_CertSubjectName(strCertName, "", 0, "", PKI_X509_LDAP)
    Debug.Print "X509_CertSubjectName(LDAP) returns " & nLen & " for " & strCertName
    strOutput = String(nLen, " ")
    nRet = X509_CertSubjectName(strCertName, strOutput, Len(strOutput), "", PKI_X509_LDAP)
    Debug.Print "[" & strOutput & "]"

End Sub

Public Sub V_Test_X509_CertThumb()
    Debug.Print "Testing X509_CertThumb code ..."
    Dim nRet As Long
    Dim strCertName As String
    Dim strHexHash As String
     
    strHexHash = String(PKI_SHA1_CHARS, " ")
    strCertName = "AliceRSASignByCarl.cer"
    nRet = X509_CertThumb(strCertName, strHexHash, Len(strHexHash), 0)
    Debug.Print "X509_CertThumb returns " & nRet & " for " & strCertName
    Debug.Print strHexHash

End Sub

Public Sub V_Test_X509_CertThumb2()
    Debug.Print "Testing X509_CertThumb vbacode ..."
    Dim strCertString As String
    strCertString = x509ReadStringFromFile("AliceRSASignByCarl.cer")
    Debug.Print strCertString
    Debug.Print "CertThumb=" & x509CertThumb(strCertString)
    strCertString = x509ReadCertStringFromP7Chain("alice_bob_carl_certs.p7c", 3)
    Debug.Print strCertString
    Debug.Print "CertThumb=" & x509CertThumb(strCertString)
    Debug.Print "HashIssuerAndSN=" & x509HashIssuerAndSN(strCertString, PKI_HASH_SHA256)

End Sub

Public Sub V_Test_X509_CheckCertInCRL()
    Debug.Print "Testing X509_CheckCertInCRL code ..."
    Dim nRet As Long
    Dim strCrlFile As String
    Dim strCertFile As String
    Dim strDate As String
    
    ' Use test CRL and certs from RFC3280
    strCrlFile = "rfc3280bis_CRL.crl"
    ' This cert has not been revoked.
    strCertFile = "rfc3280bis_cert1.cer"
    Debug.Print "CrlFile=" & strCrlFile
    Debug.Print "CertFile=" & strCertFile
    nRet = X509_CheckCertInCRL(strCertFile, strCrlFile, "", "", 0)
    Debug.Print "X509_CheckCertInCRL returns " & nRet
    If nRet = PKI_X509_REVOKED Then
      Debug.Print "CERT HAS BEEN REVOKED"
    ElseIf nRet = 0 Then
      Debug.Print "Cert has not been revoked"
    Else
      Debug.Print "ERROR: " & pkiErrorLookup(nRet) & ": " & pkiGetLastError()
    End If
    
    ' This cert has been revoked.
    strCertFile = "rfc3280bis_cert2.cer"
    Debug.Print "CrlFile=" & strCrlFile
    Debug.Print "CertFile=" & strCertFile
    nRet = X509_CheckCertInCRL(strCertFile, strCrlFile, "", "", 0)
    Debug.Print "X509_CheckCertInCRL returns " & nRet
    If nRet = PKI_X509_REVOKED Then
      Debug.Print "CERT HAS BEEN REVOKED"
    ElseIf nRet = 0 Then
      Debug.Print "Cert has not been revoked"
    Else
      Debug.Print "ERROR: " & pkiErrorLookup(nRet) & ": " & pkiGetLastError()
    End If
    
    ' But the same cert was not revoked as at 15:00 GMT on 19 November 2004
    strCertFile = "rfc3280bis_cert2.cer"
    strDate = "2004-11-19T15:00Z"
    Debug.Print "CrlFile=" & strCrlFile
    Debug.Print "CertFile=" & strCertFile
    Debug.Print "Date=" & strDate
    nRet = X509_CheckCertInCRL(strCertFile, strCrlFile, "", strDate, 0)
    Debug.Print "X509_CheckCertInCRL(" & strDate & ") returns " & nRet
    If nRet = PKI_X509_REVOKED Then
      Debug.Print "CERT HAS BEEN REVOKED"
    ElseIf nRet = 0 Then
      Debug.Print "Cert has not been revoked"
    Else
      Debug.Print "ERROR: " & pkiErrorLookup(nRet) & ": " & pkiGetLastError()
    End If

End Sub

Public Sub V_Test_X509_GetCertFromP7Chain()
    Debug.Print "Testing X509_GetCertFromP7Chain code ..."
    Dim nRet As Long
    Dim strListFile As String
    Dim strCertFile As String
    Dim nCerts As Long
    Dim iCert As Long
    
    strListFile = "bob.p7b"
    ' How many certificates?  - NB new function in [v12.2]
    nCerts = X509_GetCertCountInP7Chain(strListFile, 0)
    Debug.Print "X509_GetCertCountInP7Chain returns " & nCerts & " for " & strListFile
    ' Enumerate through them all
    If nCerts > 0 Then
        For iCert = 1 To nCerts
            strCertFile = "bobcert" & iCert & ".cer"
            nRet = X509_GetCertFromP7Chain(strCertFile, strListFile, iCert, 0)
            Debug.Print "X509_GetCertFromP7Chain(" & iCert & ") returns " _
                & nRet & "->" & strCertFile
        Next
    End If

End Sub

Public Sub V_Test_X509_HashIssuerAndSN()
    Debug.Print "Testing X509_HashIssuerAndSN code ..."
        Dim nRet As Long
        Dim strCertName As String
        Dim strOutput As String * PKI_MAX_HASH_CHARS
         
        strCertName = "BobRSASignByCarl.cer"    ' Set dir to suit
        nRet = X509_HashIssuerAndSN(strCertName, strOutput, Len(strOutput), 0)
        Debug.Print "X509_HashIssuerAndSN returns " & nRet & " for " & strCertName & ": " & Left(strOutput, nRet)

End Sub

Public Sub V_Test_X509_HashIssuerAndSN2()
    Debug.Print "Testing X509_HashIssuerAndSN vbacode ..."
    Dim strCertString As String
    strCertString = x509ReadStringFromFile("AliceRSASignByCarl.cer")
    Debug.Print strCertString
    Debug.Print "CertThumb=" & x509CertThumb(strCertString)
    strCertString = x509ReadCertStringFromP7Chain("alice_bob_carl_certs.p7c", 3)
    Debug.Print strCertString
    Debug.Print "CertThumb=" & x509CertThumb(strCertString)
    Debug.Print "HashIssuerAndSN=" & x509HashIssuerAndSN(strCertString, PKI_HASH_SHA256)

End Sub

Public Sub V_Test_X509_KeyUsageFlags()
    Debug.Print "Testing X509_KeyUsageFlags code ..."
    Dim nRet As Long
    Dim strCertName As String
    strCertName = "CarlRSASelf.cer"
    nRet = X509_KeyUsageFlags(strCertName)
    ' Show the result as a hex number
    Debug.Print "keyUsage flags are (0x" & Hex(nRet) & "):"
    ' Check all the keyUsage flags in turn
    If (nRet And PKI_X509_KEYUSAGE_DIGITALSIGNATURE) <> 0 Then Debug.Print "digitalSignature"
    If (nRet And PKI_X509_KEYUSAGE_NONREPUDIATION) <> 0 Then Debug.Print "nonRepudiation"
    If (nRet And PKI_X509_KEYUSAGE_KEYENCIPHERMENT) <> 0 Then Debug.Print "keyEncipherment"
    If (nRet And PKI_X509_KEYUSAGE_DATAENCIPHERMENT) <> 0 Then Debug.Print "dataEncipherment"
    If (nRet And PKI_X509_KEYUSAGE_KEYAGREEMENT) <> 0 Then Debug.Print "keyAgreement"
    If (nRet And PKI_X509_KEYUSAGE_KEYCERTSIGN) <> 0 Then Debug.Print "keyCertSign"
    If (nRet And PKI_X509_KEYUSAGE_CRLSIGN) <> 0 Then Debug.Print "cRLSign"
    If (nRet And PKI_X509_KEYUSAGE_ENCIPHERONLY) <> 0 Then Debug.Print "encipherOnly"
    If (nRet And PKI_X509_KEYUSAGE_DECIPHERONLY) <> 0 Then Debug.Print "decipherOnly"
    
    ' Alternatively, use X509_QueryCert to find these values as a string directly
    Debug.Print "Use X509_QueryCert..."
    Dim strOutput As String
    Dim strQuery As String
    Dim nChars As Long
    strQuery = "keyUsageString"
    nChars = X509_QueryCert("", 0, strCertName, strQuery, 0)
    If nChars < 0 Then Exit Sub  ' ERROR
    strOutput = String(nChars, " ")
    nChars = X509_QueryCert(strOutput, Len(strOutput), strCertName, strQuery, 0)
    Debug.Print "X509_QueryCert('" & strQuery & "')=" & strOutput

End Sub

Public Sub V_Test_X509_MakeCert()
    Debug.Print "Testing X509_MakeCert code ..."
    Dim nRet As Long
    Dim strNewCertFile As String
    Dim strIssuerCert As String
    Dim strSubjectPubKeyFile As String
    Dim strIssuerPriKeyFile As String
    Dim strPassword As String
    Dim nCertNum As Long
    Dim nYearsValid As Long
    Dim strDistName As String
    Dim strEmail As String
    strNewCertFile = "myuser.cer"
    strIssuerCert = "myca.cer"
    strSubjectPubKeyFile = "mykey.pub"
    strIssuerPriKeyFile = "myca.p8e"
    strPassword = "password"  '!!
    nCertNum = &H101
    nYearsValid = 4
    strDistName = "CN=My User;O=Test Org;OU=Unit;C=AU;L=My Town;S=State;E=myuser@testorg.com"
    strEmail = "myuser@testorg.com"
    
    nRet = X509_MakeCert(strNewCertFile, strIssuerCert, strSubjectPubKeyFile, strIssuerPriKeyFile, _
        nCertNum, nYearsValid, strDistName, strEmail, 0, strPassword, 0)
    If nRet <> 0 Then
        Debug.Print nRet & " " & pkiErrorLookup(nRet)
    Else
        Debug.Print "Success, created X.509 cert " & strNewCertFile
    End If

End Sub

Public Sub V_Test_X509_MakeCertSelf()
    Debug.Print "Testing X509_MakeCertSelf code ..."
    Dim nRet As Long
    Dim nKeyUsage As Long
    
    nKeyUsage = PKI_X509_KEYUSAGE_DIGITALSIGNATURE + _
        PKI_X509_KEYUSAGE_KEYCERTSIGN + PKI_X509_KEYUSAGE_CRLSIGN
    nRet = X509_MakeCertSelf("myca.cer", "myca.p8e", 99, 10, _
        "CN=My CA;O=Test Org;OU=Certificate Services", _
        "", nKeyUsage, "password", 0)
    If nRet <> 0 Then
        Debug.Print nRet & " " & pkiGetLastError()
    Else
        Debug.Print "Success"
    End If

End Sub

Public Sub V_Test_X509_MakeCertSelf2()
    Debug.Print "Testing X509_MakeCertSelf code ..."
    Dim nRet As Long
    Dim nKeyUsage As Long
    Dim strDN As String
    
    ' Specify DN using chinese characters in UTF-8
    ' CN=da wei (U+5927, U+536B)
    ' C=zhong guo (U+4E2D, U+56FD)
    strDN = "CN=#xE5A4A7E58DAB;C=#xe4b8ade59bbd"
    nKeyUsage = PKI_X509_KEYUSAGE_DIGITALSIGNATURE + PKI_X509_KEYUSAGE_KEYCERTSIGN + PKI_X509_KEYUSAGE_CRLSIGN
    nRet = X509_MakeCertSelf("myca-chinadavid.cer", "myca.p8e", _
        &H888, 4, strDN, "", nKeyUsage, "password", PKI_X509_UTF8)
    If nRet <> 0 Then
        Debug.Print nRet & " " & pkiGetLastError()
    Else
        Debug.Print "Success"
    End If

End Sub

Public Sub V_Test_X509_MakeCRL()
    Debug.Print "Testing X509_MakeCRL code ..."
    Dim nRet As Long
    Dim strCrlFile As String
    Dim strIssuerFile As String
    Dim strKeyFile As String
    Dim strPassword As String
    Dim strCertList As String
    Dim strExtension As String
    ' Create a new CRL dated with the current system time
    strCrlFile = "CarlsNew.crl"
    strIssuerFile = "CarlRSASelf.cer"
    strKeyFile = "CarlPrivRSASign.p8e"
    ' CAUTION: DO NOT HARD-CODE REAL PASSWORDS!
    strPassword = "password"
    strCertList = "1,2007-12-31; 2, 2009-12-31T12:59:59Z; 66000,2066-01-01; #x0102deadbeef,2010-02-28T01:01:59"
    nRet = X509_MakeCRL(strCrlFile, strIssuerFile, strKeyFile, strPassword, strCertList, "", 0)
    Debug.Print "X509_MakeCRL returns " & nRet & " (expected 0)"
    If (nRet = 0) Then
      Debug.Print "SUCCESS: New CRL file '" & strCrlFile & "' created."
    Else
      Debug.Print "ERROR: " & pkiErrorLookup(nRet) & ": " & pkiGetLastError()
    End If
    ' Create another CRL using specified times (NB these are GMT times, not local)
    strExtension = "thisUpdate=2010-04-01T12:00;nextUpdate=2010-05-01"
    strCrlFile = "Carl_20100401.crl"
    nRet = X509_MakeCRL(strCrlFile, strIssuerFile, strKeyFile, strPassword, strCertList, strExtension, 0)
    Debug.Print "X509_MakeCRL returns " & nRet & " (expected 0)"
    If (nRet = 0) Then
      Debug.Print "SUCCESS: New CRL file '" & strCrlFile & "' created."
    Else
      Debug.Print "ERROR: " & pkiErrorLookup(nRet) & ": " & pkiGetLastError()
    End If

End Sub

Public Sub V_Test_X509_QueryCert()
    Debug.Print "Testing X509_QueryCert vbacode ..."
    Debug.Print x509TextDumpToString("AliceRSASignByCarl.cer")
    Debug.Print x509QueryCert("AliceRSASignByCarl.cer", "subjectName")
    Debug.Print asn1TextDumpToString("AliceRSASignByCarl.cer")

End Sub

Public Sub V_Test_X509_ReadCertStringFromP7Chain()
    Debug.Print "Testing X509_ReadCertStringFromP7Chain code ..."
    Dim strP7 As String
    Dim nCerts As Long
    Dim nChars As Long
    Dim nIndex As Long
    Dim strCert As String
    Dim strDigest As String * PKI_SHA1_CHARS
    Dim strQuery As String * 128
    
    ' Input is a P7 chain file in PEM format
    ' bob.p7b (contains 2 X.509 certs: BobRSA and CarlRSA)
    strP7 = "-----BEGIN PKCS7-----" & _
        "MIIERQYJKoZIhvcNAQcCoIIENjCCBDICAQExADALBgkqhkiG9w0BBwGgggQaMIICJzCCAZCgAwIB" & _
        "AgIQRjRrx4AAVrwR024uzV1x0DANBgkqhkiG9w0BAQUFADASMRAwDgYDVQQDEwdDYXJsUlNBMB4X" & _
        "DTk5MDkxOTAxMDkwMloXDTM5MTIzMTIzNTk1OVowETEPMA0GA1UEAxMGQm9iUlNBMIGfMA0GCSqG" & _
        "SIb3DQEBAQUAA4GNADCBiQKBgQCp4WeYPznVX/Kgk0FepnmJhcg1XZqRW/sdAdoZcCYXD72lItA1" & _
        "hW16mGYUQVzPt7cIOwnJkbgZaTdt+WUee9mpMySjfzu7r0YBhjY0MssHA1lS/IWLMQS4zBgIFEjm" & _
        "Txz7XWDE4FwfU9N/U9hpAfEF+Hpw0b6Dxl84zxwsqmqn6wIDAQABo38wfTAMBgNVHRMBAf8EAjAA" & _
        "MA4GA1UdDwEB/wQEAwIFIDAfBgNVHSMEGDAWgBTp4JAnrHggeprTTPJCN04irp44uzAdBgNVHQ4E" & _
        "FgQU6PS4Z9izlqQq8xGqKdOVWoYWtCQwHQYDVR0RBBYwFIESQm9iUlNBQGV4YW1wbGUuY29tMA0G" & _
        "CSqGSIb3DQEBBQUAA4GBAHuOZsXxED8QIEyIcat7QGshM/pKld6dDltrlCEFwPLhfirNnJOIh/uL" & _
        "t359QWHh5NZt+eIEVWFFvGQnRMChvVl52R1kPCHWRbBdaDOS6qzxV+WBfZjmNZGjOd539OgcOync" & _
        "f1EHl/M28FAK3Zvetl44ESv7V+qJba3JiNiPzyvTMIIB6zCCAVSgAwIBAgIQRjRrx4AAVrwR024u" & _
        "n/JQIDANBgkqhkiG9w0BAQUFADASMRAwDgYDVQQDEwdDYXJsUlNBMB4XDTk5MDgxODA3MDAwMFoX" & _
        "DTM5MTIzMTIzNTk1OVowEjEQMA4GA1UEAxMHQ2FybFJTQTCBnzANBgkqhkiG9w0BAQEFAAOBjQAw" & _
        "gYkCgYEA5Ev/GLgkV/R3/25ze5NxXLwzGpKSciPYQUbQzRE6BLOOr4KdvVEeF3rydiwrhjmnvdeN" & _
        "GlPs5ADV6OyiNrHt4lDiMgmKP5+ZJY+4Tqu5fdWWZdoWoMW+Dq5EW+9e9Kcpy4LdrETpqpOUKQ74" & _
        "GNbIV17ydsTyEWA4uRs8HZfJavECAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8E" & _
        "BAMCAYYwHQYDVR0OBBYEFOngkCeseCB6mtNM8kI3TiKunji7MA0GCSqGSIb3DQEBBQUAA4GBALee" & _
        "1ATT7Snk/4mJFS5M2wzwSA8yYe7EBOwSXS3/D2RZfgrD7Rj941ZAN6cHtfA4EmFQ7e/dP+MLuGGl" & _
        "pJs85p6cVJq2ldbabDu1LUU1nUkBdvq5uTH5+WsSU6D1FGCbfco+8lNrsDdvreZ019v6WuoUQWNd" & _
        "zb7IDsHaao1TNBgCMQA=" & _
        "-----END PKCS7-----"
    ' Get count of certs in P7 chain - new function in [v12.2]
    nIndex = 0
    nCerts = X509_GetCertCountInP7Chain(strP7, 0)
    Debug.Print "nCerts=" & nCerts
    ' Read all certs
    For nIndex = 1 To nCerts
    ' Find required length of buffer
    nChars = X509_ReadCertStringFromP7Chain(ByVal 0&, 0, strP7, nIndex, 0)
    Debug.Print "X509_ReadCertStringFromP7Chain(" & nIndex & ") returns " & nChars
    ' Allocate memory/pre-dimension
    strCert = String(nChars, " ")
    nChars = X509_ReadCertStringFromP7Chain(strCert, Len(strCert), strP7, nIndex, 0)
    ' Cert is in a base64 string
    Debug.Print Left(strCert, 150) & "..."
    ' Query the cert for subject name
    nChars = X509_QueryCert(strQuery, Len(strQuery), strCert, "subjectName", 0)
    Debug.Print "subjectName='" & Left(strQuery, nChars) & "'"
    ' Compute the SHA-1 thumbprint of the cert
    nChars = X509_CertThumb(strCert, strDigest, Len(strDigest), 0)
    Debug.Print "SHA-1(cert)=" & Left(strDigest, nChars)
    Next

End Sub

Public Sub V_Test_X509_ReadCertStringFromP7Chain2()
    Debug.Print "Testing X509_ReadCertStringFromP7Chain vbacode ..."
    Dim strCertString As String
    strCertString = x509ReadStringFromFile("AliceRSASignByCarl.cer")
    Debug.Print strCertString
    Debug.Print "CertThumb=" & x509CertThumb(strCertString)
    strCertString = x509ReadCertStringFromP7Chain("alice_bob_carl_certs.p7c", 3)
    Debug.Print strCertString
    Debug.Print "CertThumb=" & x509CertThumb(strCertString)
    Debug.Print "HashIssuerAndSN=" & x509HashIssuerAndSN(strCertString, PKI_HASH_SHA256)
    
    'Invalid index
    strCertString = x509ReadCertStringFromP7Chain("alice_bob_carl_certs.p7c", 0)
    Debug.Print "[" & strCertString & "]"
    
    Dim strP7File As String
    Dim nIndex As Long
    Dim nCerts As Long
    strP7File = "alice_bob_carl_certs.p7c"
    ' Call core fn with zero index to find count
    nCerts = X509_ReadCertStringFromP7Chain("", 0, strP7File, 0, 0)
    Debug.Print "nCerts=" & nCerts
    For nIndex = 1 To nCerts
        strCertString = x509ReadCertStringFromP7Chain(strP7File, nIndex)
        Debug.Print "subjectName: " & x509QueryCert(strCertString, "subjectName")
    Next

End Sub

Public Sub V_Test_X509_ReadCertStringFromPFX()
    Debug.Print "Testing X509_ReadCertStringFromPFX vbacode ..."
    Dim strCertString As String
    strCertString = x509ReadCertStringFromPFX("alice.p12", "password")
    Debug.Print strCertString
    Debug.Print "CertThumb=" & x509CertThumb(strCertString)
    Debug.Print "HashIssuerAndSN=" & x509HashIssuerAndSN(strCertString)

End Sub

Public Sub V_Test_X509_ReadStringFromFile()
    Debug.Print "Testing X509_ReadStringFromFile vbacode ..."
    Dim strCertString As String
    strCertString = x509ReadStringFromFile("AliceRSASignByCarl.cer")
    Debug.Print strCertString
    Debug.Print "CertThumb=" & x509CertThumb(strCertString)
    strCertString = x509ReadCertStringFromP7Chain("alice_bob_carl_certs.p7c", 3)
    Debug.Print strCertString
    Debug.Print "CertThumb=" & x509CertThumb(strCertString)
    Debug.Print "HashIssuerAndSN=" & x509HashIssuerAndSN(strCertString, PKI_HASH_SHA256)

End Sub

Public Sub V_Test_X509_TextDump()
    Debug.Print "Testing X509_TextDump code ..."
    Dim nRet As Long
    Dim strInputFile As String
    Dim strOutFile As String
    
    strInputFile = "AliceRSASignByCarl.cer"
    strOutFile = "dump-AliceRSASignByCarl.cer.txt"
    Debug.Print "File=" & strInputFile
    nRet = X509_TextDump(strOutFile, strInputFile, 0)
    Debug.Print "X509_TextDump returns " & nRet

End Sub

Public Sub V_Test_X509_TextDumpToString()
    Debug.Print "Testing X509_TextDumpToString code ..."
    Dim strInputFile As String
    Dim strBuffer As String
    Dim nChars As Long
    
    strInputFile = "AliceRSASignByCarl.cer"
    Debug.Print "File=" & strInputFile
    ' Query for required length
    nChars = X509_TextDumpToString("", 0, strInputFile, PKI_X509_DECIMAL)
    Debug.Print "X509_TextDumpToString returns " & nChars
    ' Dimension output buffer
    strBuffer = String(nChars, " ")
    nChars = X509_TextDumpToString(strBuffer, Len(strBuffer), strInputFile, PKI_X509_DECIMAL)
    Debug.Print strBuffer

End Sub

Public Sub V_Test_X509_TextDumpToString2()
    Debug.Print "Testing X509_TextDumpToString vbacode ..."
    Debug.Print x509TextDumpToString("AliceRSASignByCarl.cer")
    Debug.Print x509QueryCert("AliceRSASignByCarl.cer", "subjectName")
    Debug.Print asn1TextDumpToString("AliceRSASignByCarl.cer")
End Sub

Public Sub V_Test_X509_ValidatePath()
    Debug.Print "Testing X509_ValidatePath code ..."
    Dim nRet As Long
    Dim strP7cFile As String
    Dim strTrustedCert As String
    Dim strCertList As String
    
    ' A p7c "certs-only" file which includes a self-signed cert
    strP7cFile = "testcerts1.p7c"
    nRet = X509_ValidatePath(strP7cFile, "", 0)
    Debug.Print "X509_ValidatePath returns " & nRet & " (expected 0)"
    
    ' Same again but specify the trusted root cert
    ' (which is the same as the self-signed cert in the p7c file)
    strP7cFile = "testcerts1.p7c"
    strTrustedCert = "testcert00.cer"
    nRet = X509_ValidatePath(strP7cFile, strTrustedCert, 0)
    Debug.Print "X509_ValidatePath returns " & nRet & " (expected 0)"
    
    ' Specify a cert list - testcert00.cer is the self-signed cert
    strCertList = "testcert00.cer;testcert03.cer;testcert01.cer;testcert02.cer"
    nRet = X509_ValidatePath(strCertList, "", 0)
    Debug.Print "X509_ValidatePath returns " & nRet & " (expected 0)"
    
    ' Same again but specify the trusted root cert (this time it is not in the list)
    strCertList = "testcert01.cer;testcert02.cer;testcert03.cer"
    strTrustedCert = "testcert00.cer"
    nRet = X509_ValidatePath(strCertList, strTrustedCert, 0)
    Debug.Print "X509_ValidatePath returns " & nRet & " (expected 0)"

End Sub

Public Sub V_Test_X509_VerifyCert()
    Debug.Print "Testing X509_VerifyCert code ..."
    ' Returns 0 if OK, PKI_X509_VERIFY_FAILURE if fails to validate, or +ve other error
    Dim nRet As Long
    nRet = X509_VerifyCert("myuser.cer", "myca.cer", 0)
    If nRet = 0 Then
        Debug.Print "Verification is OK"
    ElseIf nRet = PKI_X509_VERIFY_FAILURE Then
        Debug.Print "Cert not issued by this Issuer"
    Else
        Debug.Print "Error: " & nRet & pkiGetLastError()
    End If

End Sub

Public Sub V_Test_X509_VerifyCert2()
    Debug.Print "Testing X509_VerifyCert code ..."
    Dim nRet As Long
    nRet = X509_VerifyCert("myreq.p10.txt", "", 0)
    If nRet = 0 Then
        Debug.Print "Verification is OK"
    ElseIf nRet = PKI_X509_VERIFY_FAILURE Then
        Debug.Print "Signature is invalid"
    Else
        Debug.Print "Error: " & nRet & pkiGetLastError()
    End If

End Sub

Public Sub V_Test_XOF_Bytes()
    Debug.Print "Testing XOF_Bytes vbacode ..."
    Dim lpMessage() As Byte
    Dim lpOut() As Byte
    lpMessage = cnvFromHex("6ae23f058f0f2264a18cd609acc26dd4dbc00f5c3ee9e13ecaea2bb5a2f0bb6b")
    ' Output 2000 bits
    lpOut = xofBytes(2000 \ 8, lpMessage, PKI_XOF_SHAKE256)
    Debug.Print "OUT=" & cnvToHex(lpOut)
    Debug.Print "OK =" & "b9b92544fb25cf...f1d35bdff79a"
    ' MGF1-SHA-256
    lpMessage = cnvFromHex("3b5c056af3ebba70d4c805380420585562b32410a778f558ff951252407647e3")
    Debug.Print cnvToHex(lpMessage)
    lpOut = xofBytes(34, lpMessage, PKI_XOF_MGF1_SHA256)
    Debug.Print "OUT=" & cnvToHex(lpOut)
    Debug.Print "OK =" & "5b7eb772aecf04c74af07d9d9c1c1f8d3a90dcda00d5bab1dc28daecdc86eb87611e"

End Sub

Public Sub V_DoAllTests()
    Call V_Test_ASN1_TextDump
    Call V_Test_ASN1_TextDumpToString
    Call V_Test_ASN1_TextDumpToString2
    Call V_Test_ASN1_TextDumpToString3
    Call V_Test_ASN1_Type
    Call V_Test_ASN1_Type2
    Call V_Test_CIPHER_Bytes
    Call V_Test_CIPHER_DecryptAEAD
    Call V_Test_CIPHER_DecryptAEAD2
    Call V_Test_CIPHER_DecryptAEAD3
    Call V_Test_CIPHER_DecryptBytes
    Call V_Test_CIPHER_DecryptBytes2
    Call V_Test_CIPHER_DecryptHex
    Call V_Test_CIPHER_DecryptHex2
    Call V_Test_CIPHER_EncryptAEAD
    Call V_Test_CIPHER_EncryptAEAD2
    Call V_Test_CIPHER_EncryptBytes
    Call V_Test_CIPHER_EncryptBytes2
    Call V_Test_CIPHER_EncryptHex
    Call V_Test_CIPHER_EncryptHex2
    Call V_Test_CIPHER_File
    Call V_Test_CIPHER_FileEncrypt
    Call V_Test_CIPHER_Hex
    Call V_Test_CIPHER_KeyWrap
    Call V_Test_CIPHER_KeyWrap2
    Call V_Test_CIPHER_KeyUnwrap
    Call V_Test_CIPHER_KeyUnwrap2
    Call V_Test_CMS_GetSigDataDigest
    Call V_Test_CMS_GetSigDataDigest2
    Call V_Test_CMS_GetSigDataDigest3
    Call V_Test_CMS_MakeComprData
    Call V_Test_CMS_MakeDetachedSig
    Call V_Test_CMS_MakeEnvData
    Call V_Test_CMS_MakeEnvData2
    Call V_Test_CMS_MakeEnvData3
    Call V_Test_CMS_MakeEnvData4
    Call V_Test_CMS_MakeEnvData5
    Call V_Test_CMS_MakeEnvDataFromBytes
    Call V_Test_CMS_MakeEnvDataFromString
    Call V_Test_CMS_MakeEnvDataFromString2
    Call V_Test_CMS_MakeSigData
    Call V_Test_CMS_MakeSigData2
    Call V_Test_CMS_MakeSigDataFromSigValue
    Call V_Test_CMS_MakeSigDataFromBytes
    Call V_Test_CMS_MakeSigDataFromBytes2
    Call V_Test_CMS_QueryEnvData
    Call V_Test_CMS_QuerySigData
    Call V_Test_CMS_ReadEnvData
    Call V_Test_CMS_ReadEnvDataToBytes
    Call V_Test_CMS_ReadEnvDataToBytes2
    Call V_Test_CMS_ReadEnvDataToString
    Call V_Test_CMS_ReadEnvDataToString2
    Call V_Test_CMS_ReadSigData
    Call V_Test_CMS_ReadSigDataToBytes
    Call V_Test_CMS_ReadSigDataToBytes2
    Call V_Test_CMS_ReadSigDataToString
    Call V_Test_CMS_ReadSigDataToString2
    Call V_Test_CMS_VerifySigData
    Call V_Test_CNV_Base58FromBytes
    Call V_Test_CNV_Base58FromBytes2
    Call V_Test_CNV_Base58ToBytes
    Call V_Test_CNV_Base58ToBytes2
    Call V_Test_CNV_ByteEncoding
    Call V_Test_CNV_ByteEncoding2
    Call V_Test_CNV_CheckUTF8Bytes
    Call V_Test_CNV_CheckUTF8File
    Call V_Test_CNV_Latin1FromUTF8Bytes
    Call V_Test_CNV_Latin1FromUTF8Bytes2
    Call V_Test_CNV_Latin1FromUTF8Bytes3
    Call V_Test_CNV_NumFromBytes
    Call V_Test_CNV_NumToBytes
    Call V_Test_CNV_NumToBytes2
    Call V_Test_CNV_ReverseBytes
    Call V_Test_CNV_UTF8BytesFromLatin1
    Call V_Test_CNV_UTF8BytesFromLatin12
    Call V_Test_CNV_UTF8BytesFromLatin13
    Call V_Test_COMPR_Compress
    Call V_Test_COMPR_Compress2
    Call V_Test_COMPR_Uncompress
    Call V_Test_ECC_DHSharedSecret
    Call V_Test_ECC_DHSharedSecret2
    Call V_Test_ECC_KeyHashCode
    Call V_Test_ECC_PublicKeyFromPrivate
    Call V_Test_ECC_PublicKeyFromPrivate2
    Call V_Test_ECC_QueryKey
    Call V_Test_ECC_QueryKey2
    Call V_Test_ECC_ReadKeyByCurve
    Call V_Test_ECC_ReadKeyByCurve2
    Call V_Test_ECC_ReadKeyByCurve3
    Call V_Test_ECC_ReadPrivateKey
    Call V_Test_ECC_ReadPrivateKey2
    Call V_Test_ECC_ReadPublicKey
    Call V_Test_ECC_ReadPublicKey2
    Call V_Test_ECC_SaveEncKey
    Call V_Test_ECC_SaveKey
    Call V_Test_HASH_Bytes
    Call V_Test_HASH_Bytes2
    Call V_Test_HASH_Bytes3
    Call V_Test_HASH_File
    Call V_Test_HASH_File2
    Call V_Test_HASH_HexFromBytes
    Call V_Test_HASH_HexFromBytes2
    Call V_Test_HASH_HexFromBytes3
    Call V_Test_HASH_HexFromBytes4
    Call V_Test_HASH_HexFromFile
    Call V_Test_HASH_HexFromFile2
    Call V_Test_HASH_HexFromHex
    Call V_Test_HASH_HexFromHex2
    Call V_Test_HASH_Length
    Call V_Test_HASH_Length2
    Call V_Test_HMAC_Bytes
    Call V_Test_HMAC_Bytes2
    Call V_Test_HMAC_Bytes3
    Call V_Test_HMAC_HexFromBytes
    Call V_Test_HMAC_HexFromBytes2
    Call V_Test_HMAC_HexFromHex
    Call V_Test_HMAC_HexFromHex2
    Call V_Test_KDF_Bytes
    Call V_Test_KDF_Bytes2
    Call V_Test_KDF_ForCms
    Call V_Test_KDF_ForCms2
    Call V_Test_OCSP_MakeRequest
    Call V_Test_OCSP_MakeRequest2
    Call V_Test_OCSP_ReadResponse
    Call V_Test_OCSP_ReadResponse2
    Call V_Test_PAD_BytesBlock
    Call V_Test_PAD_BytesBlock2
    Call V_Test_PAD_HexBlock
    Call V_Test_PAD_HexBlock2
    Call V_Test_PAD_UnpadBytes
    Call V_Test_PAD_UnpadHex
    Call V_Test_PAD_UnpadHex2
    Call V_Test_PBE_Kdf2
    Call V_Test_PBE_Kdf22
    Call V_Test_PBE_Kdf23
    Call V_Test_PBE_Kdf2Hex
    Call V_Test_PBE_Kdf2Hex2
    Call V_Test_PEM_FileFromBinFile
    Call V_Test_PEM_FileToBinFile
    Call V_Test_PFX_MakeFile
    Call V_Test_PFX_MakeFile2
    Call V_Test_PKI_CompileTime
    Call V_Test_PKI_CompileTime2
    Call V_Test_PKI_ErrorCode
    Call V_Test_PKI_ErrorLookup
    Call V_Test_PKI_ErrorLookup2
    Call V_Test_PKI_LastError
    Call V_Test_PKI_LicenceType
    Call V_Test_PKI_ModuleInfo
    Call V_Test_PKI_ModuleName
    Call V_Test_PKI_ModuleName2
    Call V_Test_PKI_Platform
    Call V_Test_PKI_PowerUpTests
    Call V_Test_PKI_Version
    Call V_Test_PRF_Bytes
    Call V_Test_RNG_Bytes
    Call V_Test_RNG_Bytes2
    Call V_Test_RNG_Guid
    Call V_Test_RNG_Guid2
    Call V_Test_RNG_Initialize
    Call V_Test_RNG_Number
    Call V_Test_RNG_Test
    Call V_Test_RSA_DecodeMsg
    Call V_Test_RSA_DecodeMsg2
    Call V_Test_RSA_EncodeMsg
    Call V_Test_RSA_EncodeMsg2
    Call V_Test_RSA_Encrypt
    Call V_Test_RSA_Encrypt2
    Call V_Test_RSA_FromXMLString
    Call V_Test_RSA_FromXMLString2
    Call V_Test_RSA_FromXMLString3
    Call V_Test_RSA_GetPublicKeyFromCert
    Call V_Test_RSA_KeyMatch
    Call V_Test_RSA_KeyValue
    Call V_Test_RSA_KeyValue2
    Call V_Test_RSA_MakeKeys
    Call V_Test_RSA_MakeKeysXtd2
    Call V_Test_RSA_PublicKeyFromPrivate
    Call V_Test_RSA_PublicKeyFromPrivate2
    Call V_Test_RSA_RawPrivate
    Call V_Test_RSA_RawPrivate2
    Call V_Test_RSA_RawPublic
    Call V_Test_RSA_RawPublic2
    Call V_Test_RSA_ReadAnyPrivateKey
    Call V_Test_RSA_ReadAnyPublicKey
    Call V_Test_RSA_ReadAnyPublicKey2
    Call V_Test_RSA_ReadPrivateKeyFromPFX
    Call V_Test_RSA_ReadPrivateKeyInfo
    Call V_Test_RSA_SaveEncPrivateKey
    Call V_Test_RSA_SavePrivateKeyInfo
    Call V_Test_RSA_ToXMLString
    Call V_Test_RSA_ToXMLString2
    Call V_Test_RSA_ToXMLStringEx
    Call V_Test_SIG_SignData
    Call V_Test_SIG_SignData2
    Call V_Test_SIG_SignData3
    Call V_Test_SIG_SignFile
    Call V_Test_SIG_SignFile2
    Call V_Test_SIG_VerifyData
    Call V_Test_SIG_VerifyFile
    Call V_Test_SMIME_Extract
    Call V_Test_SMIME_Query
    Call V_Test_SMIME_Query2
    Call V_Test_SMIME_Wrap
    Call V_Test_TDEA_B64Mode
    Call V_Test_TDEA_BytesMode
    Call V_Test_TDEA_File
    Call V_Test_TDEA_HexMode
    Call V_Test_WIPE_Data
    Call V_Test_WIPE_Data2
    Call V_Test_WIPE_Data3
    Call V_Test_WIPE_File
    Call V_Test_X509_CertExpiresOn
    Call V_Test_X509_CertIsValidNow
    Call V_Test_X509_CertRequest
    Call V_Test_X509_CertRequest2
    Call V_Test_X509_CertSerialNumber
    Call V_Test_X509_CertSubjectName
    Call V_Test_X509_CertThumb
    Call V_Test_X509_CertThumb2
    Call V_Test_X509_CheckCertInCRL
    Call V_Test_X509_GetCertFromP7Chain
    Call V_Test_X509_HashIssuerAndSN
    Call V_Test_X509_HashIssuerAndSN2
    Call V_Test_X509_KeyUsageFlags
    Call V_Test_X509_MakeCert
    Call V_Test_X509_MakeCertSelf
    Call V_Test_X509_MakeCertSelf2
    Call V_Test_X509_MakeCRL
    Call V_Test_X509_QueryCert
    Call V_Test_X509_ReadCertStringFromP7Chain
    Call V_Test_X509_ReadCertStringFromP7Chain2
    Call V_Test_X509_ReadCertStringFromPFX
    Call V_Test_X509_ReadStringFromFile
    Call V_Test_X509_TextDump
    Call V_Test_X509_TextDumpToString
    Call V_Test_X509_TextDumpToString2
    Call V_Test_X509_ValidatePath
    Call V_Test_X509_VerifyCert
    Call V_Test_X509_VerifyCert2
    Call V_Test_XOF_Bytes
Debug.Print "ALL DONE."
End Sub