Attribute VB_Name = "TestAPIvba"
Option Explicit
Option Compare Text

' $Date: 2018/09/15 17:49:00 $

Dim nRet As Long

Public Sub V_Test_AEAD_Decrypt()
    Debug.Print "Testing AEAD_Decrypt ..."
    ' Ref: RFC 7539 Appendix A.5
    Dim abKey() As Byte
    Dim abNonce() As Byte
    Dim abAAD() As Byte
    Dim abPT() As Byte
    Dim abCT() As Byte
    Dim abTag() As Byte
    
    Dim nRet As Long
    Dim nKeyLen As Long
    Dim nNonceLen As Long
    Dim nAadLen As Long
    Dim nDataLen As Long
    Dim nTagLen As Long
    Dim strPTOK As String
    
    Debug.Print "RFC7739 ChaCha20_Poly1305 Appendix A.5:"
    ' Set byte arrays from hex strings
    abKey = cnvBytesFromHexStr("1c9240a5eb55d38af333888604f6b5f0473917c1402b80099dca5cbc207075c0")
    abNonce = cnvBytesFromHexStr("000000000102030405060708")
    abAAD = cnvBytesFromHexStr("f33388860000000000004e91")
    abCT = cnvBytesFromHexStr("64a0861575861af460f062c79be643bd5e805cfd345cf389f108670ac76c8cb24c6cfc18755d43eea09ee94e382d26b0bdb7b73c321b0100d4f03b7f355894cf332f830e710b97ce98c8a84abd0b948114ad176e008d33bd60f982b1ff37c8559797a06ef4f0ef61c186324e2b3506383606907b6a7c02b0f9f6157b53c867e4b9166c767b804d46a59b5216cde7a4e99040c5a40433225ee282a1b0a06c523eaf4534d7f83fa1155b0047718cbc546a0d072b04b3564eea1b422273f548271a0bb2316053fa76991955ebd63159434ecebb4e466dae5a1073a6727627097a1049e617d91d361094fa68f0ff77987130305beaba2eda04df997b714d6c6f2c29a6ad5cb4022b02709b")
    abTag = cnvBytesFromHexStr("eead9d67890cbb22392336fea1851f38")
    
    strPTOK = "496e7465726e65742d4472616674732061726520647261667420646f63756d656e74732076616c696420666f722061206d6178696d756d206f6620736978206d6f6e74687320616e64206d617920626520757064617465642c207265706c616365642c206f72206f62736f6c65746564206279206f7468657220646f63756d656e747320617420616e792074696d652e20497420697320696e617070726f70726961746520746f2075736520496e7465726e65742d447261667473206173207265666572656e6365206d6174657269616c206f7220746f2063697465207468656d206f74686572207468616e206173202fe2809c776f726b20696e2070726f67726573732e2fe2809d"
    
    ' Set lengths of input byte arrays
    nKeyLen = UBound(abKey) + 1
    nNonceLen = UBound(abNonce) + 1
    nAadLen = UBound(abAAD) + 1
    nDataLen = UBound(abCT) + 1
    nTagLen = UBound(abTag) + 1
    
    ' Dimension arrays for output (we are decrypting CT->PT)
    ReDim abPT(nDataLen - 1)
    
    ' Display input
    Debug.Print "K: " & cnvHexStrFromBytes(abKey)
    Debug.Print "N: " & cnvHexStrFromBytes(abNonce)
    Debug.Print "A: " & cnvHexStrFromBytes(abAAD)
    Debug.Print "C: " & cnvHexStrFromBytes(abCT)
    Debug.Print "T: " & cnvHexStrFromBytes(abTag)
    
    ' Do authenticated decryption using AEAD_CHACHA20_POLY1305
    nRet = AEAD_Decrypt(abPT(0), nDataLen, abCT(0), nDataLen, _
        abKey(0), nKeyLen, abNonce(0), nNonceLen, abAAD(0), nAadLen, abTag(0), nTagLen, API_AEAD_CHACHA20_POLY1305)
    Debug.Print "AEAD_Decrypt returns " & nRet & " (expected 0)"
    Debug.Print "P: " & cnvHexStrFromBytes(abPT)
    Debug.Print "OK " & strPTOK
    ' Show plaintext as string (note the UTF-8 double quotation marks do not decode in VB6)
    Debug.Print "   " & StrConv(abPT, vbUnicode)

End Sub

Public Sub V_Test_AEAD_Encrypt()
    Debug.Print "Testing AEAD_Encrypt ..."
    ' IEEE P802.1 MACsec 2.4.1 54-byte Packet Encryption Using GCM-AES-128:
    Dim abKey() As Byte
    Dim abNonce() As Byte
    Dim abAAD() As Byte
    Dim abPT() As Byte
    Dim abCT() As Byte
    Dim abTag() As Byte
    
    Dim nRet As Long
    Dim nKeyLen As Long
    Dim nNonceLen As Long
    Dim nAadLen As Long
    Dim nDataLen As Long
    Dim nTagLen As Long
    Dim strCTOK As String
    Dim strTagOK As String
    
    Debug.Print "IEEE P802.1 MACsec 2.4.1 54-byte Packet Encryption Using GCM-AES-128:"
    ' Set byte arrays from hex strings
    abKey = cnvBytesFromHexStr("071b113b 0ca743fe cccf3d05 1f737382")
    abNonce = cnvBytesFromHexStr("f0761e8d cd3d0001 76d457ed")
    abAAD = cnvBytesFromHexStr("e20106d7 cd0df076 1e8dcd3d 88e54c2a 76d457ed")
    abPT = cnvBytesFromHexStr("08000f10 11121314 15161718 191a1b1c 1d1e1f20 21222324 25262728 292a2b2c 2d2e2f30 31323334 0004")
    
    strCTOK = "13b4c72b389dc5018e72a171dd85a5d3752274d3a019fbcaed09a425cd9b2e1c9b72eee7c9de7d52b3f3"
    strTagOK = "d6a5284f4a6d3fe22a5d6c2b960494c3"
    
    ' Set lengths of byte arrays
    nKeyLen = UBound(abKey) + 1
    nNonceLen = UBound(abNonce) + 1
    nAadLen = UBound(abAAD) + 1
    nDataLen = UBound(abPT) + 1
    nTagLen = API_AEAD_TAG_MAX_BYTES
    
    ' Dimension arrays for output
    ReDim abCT(nDataLen - 1)
    ReDim abTag(nTagLen - 1)
    
    ' Display input
    Debug.Print "K: " & cnvHexStrFromBytes(abKey)
    Debug.Print "N: " & cnvHexStrFromBytes(abNonce)
    Debug.Print "A: " & cnvHexStrFromBytes(abAAD)
    Debug.Print "P: " & cnvHexStrFromBytes(abPT)
    
    ' Do authenticated encryption using AEAD_AES_128_GCM
    nRet = AEAD_Encrypt(abCT(0), nDataLen, abTag(0), nTagLen, abPT(0), nDataLen, _
        abKey(0), nKeyLen, abNonce(0), nNonceLen, abAAD(0), nAadLen, API_AEAD_AES_128_GCM)
    Debug.Print "AEAD_Encrypt returns " & nRet & " (expected 0)"
    Debug.Print "C: " & cnvHexStrFromBytes(abCT)
    Debug.Print "OK " & strCTOK
    Debug.Print "T: " & cnvHexStrFromBytes(abTag)
    Debug.Print "OK " & strTagOK
    
    ' Do authenticated decryption overwriting input CT buffer
    nRet = AEAD_Decrypt(abCT(0), nDataLen, abCT(0), nDataLen, abKey(0), nKeyLen, _
        abNonce(0), nNonceLen, abAAD(0), nAadLen, abTag(0), nTagLen, API_AEAD_AES_128_GCM)
    Debug.Print "AEAD_Decrypt returns " & nRet & " (0 => OK)"
    Debug.Print "P':" & cnvHexStrFromBytes(abCT)
    
    ' Do authenticated encryption using AEAD_AES_128_GCM, overwriting input with output
    nRet = AEAD_Encrypt(abCT(0), nDataLen, abTag(0), nTagLen, abCT(0), nDataLen, _
        abKey(0), nKeyLen, abNonce(0), nNonceLen, abAAD(0), nAadLen, API_AEAD_AES_128_GCM)
    Debug.Print "AEAD_Encrypt returns " & nRet & " (expected 0)"
    Debug.Print "C: " & cnvHexStrFromBytes(abCT)
    Debug.Print "OK " & strCTOK
    Debug.Print "T: " & cnvHexStrFromBytes(abTag)
    Debug.Print "OK " & strTagOK

End Sub

Public Sub V_Test_AEAD_Encrypt2()
    Debug.Print "Testing AEAD_Encrypt ..."
    ' IEEE P802.1 MACsec 2.5.2 65-byte Packet Authentication Using GCM-AES-256:
    Dim abKey() As Byte
    Dim abNonce() As Byte
    Dim abAAD() As Byte
    Dim abTag() As Byte
    
    Dim nRet As Long
    Dim nKeyLen As Long
    Dim nNonceLen As Long
    Dim nAadLen As Long
    Dim nTagLen As Long
    Dim strTagOK As String
    
    Debug.Print "IEEE P802.1 MACsec 2.5.2 65-byte Packet Authentication Using GCM-AES-256:"
    ' Set byte arrays from hex strings
    abKey = cnvBytesFromHexStr("83C093B58DE7FFE1C0DA926AC43FB3609AC1C80FEE1B624497EF942E2F79A823")
    abNonce = cnvBytesFromHexStr("7CFDE9F9E33724C68932D612")
    abAAD = cnvBytesFromHexStr("84C5D513D2AAF6E5BBD2727788E523008932D6127CFDE9F9E33724C608000F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F0005")
    
    strTagOK = "6ee160e8faeca4b36c86b234920ca975"
    
    ' Set lengths of byte arrays
    nKeyLen = UBound(abKey) + 1
    nNonceLen = UBound(abNonce) + 1
    nAadLen = UBound(abAAD) + 1
    nTagLen = API_AEAD_TAG_MAX_BYTES
    
    ' Dimension arrays for output
    ReDim abTag(nTagLen - 1)
    
    ' Display input
    Debug.Print "K: " & cnvHexStrFromBytes(abKey)
    Debug.Print "N: " & cnvHexStrFromBytes(abNonce)
    Debug.Print "A: " & cnvHexStrFromBytes(abAAD)
    
    ' Do authenticated encryption using AEAD_AES_256_GCM
    ' Note that CT and PT are empty => just computing a MAC over the AAD
    nRet = AEAD_Encrypt(0, 0, abTag(0), nTagLen, 0, 0, _
        abKey(0), nKeyLen, abNonce(0), nNonceLen, abAAD(0), nAadLen, API_AEAD_AES_256_GCM)
    Debug.Print "AEAD_Encrypt returns " & nRet & " (expected 0)"
    Debug.Print "T: " & cnvHexStrFromBytes(abTag)
    Debug.Print "OK " & strTagOK
    
    ' Do authenticated decryption
    ' Note that CT and PT are empty => just authenticating the tag over the AAD
    nRet = AEAD_Decrypt(0, 0, 0, 0, abKey(0), nKeyLen, _
        abNonce(0), nNonceLen, abAAD(0), nAadLen, abTag(0), nTagLen, API_AEAD_AES_256_GCM)
    Debug.Print "AEAD_Decrypt returns " & nRet & " (0 => OK)"

End Sub

Public Sub V_Test_AES128_B64Mode()
    Debug.Print "Testing AES128_B64Mode ..."
    Dim nRet As Long
    Dim strOutput As String
    Dim strInput As String
    Dim strKey As String
    Dim strIV As String
    Dim bEncrypt As Boolean
    Dim sCorrect As String
    
    ' Case #4: Encrypting 64 bytes (4 blocks) using AES-CBC with 128-bit key
    ' Key       : 0x56e47a38c5598974bc46903dba290349
    strKey = "VuR6OMVZiXS8RpA9uikDSQ=="
    ' IV        : 0x8ce82eefbea0da3c44699ed7db51b7d9
    strIV = "jOgu776g2jxEaZ7X21G32Q=="
    ' Plaintext : 0xa0a1a2a3a4a5a6a7a8a9aaabacadaeaf
    '               b0b1b2b3b4b5b6b7b8b9babbbcbdbebf
    '               c0c1c2c3c4c5c6c7c8c9cacbcccdcecf
    '               d0d1d2d3d4d5d6d7d8d9dadbdcdddedf
    strInput = "oKGio6SlpqeoqaqrrK2ur7CxsrO0tba3uLm6u7y9vr/" _
    & "AwcLDxMXGx8jJysvMzc7P0NHS09TV1tfY2drb3N3e3w=="
    ' Ciphertext: 0xc30e32ffedc0774e6aff6af0869f71aa
    '               0f3af07a9a31a9c684db207eb0ef8e4e
    '               35907aa632c3ffdf868bb7b29d3d46ad
    '               83ce9f9a102ee99d49a53e87f4c3da55
    sCorrect = "ww4y/+3Ad05q/2rwhp9xqg868HqaManGhNsgfrDvjk" _
    & "41kHqmMsP/34aLt7KdPUatg86fmhAu6Z1JpT6H9MPaVQ=="
    
    ' Set strOutput to be same length as strInput
    strOutput = String(Len(strInput), " ")
    
    Debug.Print "KY=" & strKey
    Debug.Print "IV=" & strIV
    Debug.Print "PT=" & strInput
    nRet = AES128_B64Mode(strOutput, strInput, strKey, ENCRYPT, "CBC", strIV)
    Debug.Print "CT=" & strOutput & nRet
    Debug.Print "OK=" & sCorrect
    
    strInput = strOutput
    nRet = AES128_B64Mode(strOutput, strInput, strKey, DECRYPT, "CBC", strIV)
    Debug.Print "P'=" & strOutput; nRet

End Sub

Public Sub V_Test_AES128_Bytes()
    Debug.Print "Testing AES128_Bytes ..."
        Dim nRet As Long
        Dim abBlock() As Byte
        Dim abKey() As Byte
        Dim abPlain() As Byte
        Dim abCipher() As Byte
        Dim nBytes As Long
        
        'FIPS-197
        'C.1 AES-128 (Nk=4, Nr=10)
        'PLAINTEXT: 00112233445566778899aabbccddeeff
        'KEY: 000102030405060708090a0b0c0d0e0f
        
        ' Convert input to bytes
        abKey = cnvBytesFromHexStr("000102030405060708090a0b0c0d0e0f")
        abPlain = cnvBytesFromHexStr("00112233445566778899aabbccddeeff")
        abCipher = cnvBytesFromHexStr("69c4e0d86a7b0430d8cdb78070b4c55a")
        
        abBlock = abPlain
        nBytes = UBound(abBlock) - LBound(abBlock) + 1
        Debug.Print "KY=" & cnvHexStrFromBytes(abKey)
        Debug.Print "PT=" & cnvHexStrFromBytes(abBlock)
        ' Encrypt in one-off process
        nRet = AES128_Bytes(abBlock(0), abBlock(0), nBytes, abKey(0), ENCRYPT)
        Debug.Print "CT=" & cnvHexStrFromBytes(abBlock)
        Debug.Print "OK=" & cnvHexStrFromBytes(abCipher)
        Debug.Assert (StrConv(abBlock, vbUnicode) = StrConv(abCipher, vbUnicode))
        
        ' Now decrypt back to plain text
        nRet = AES128_Bytes(abBlock(0), abBlock(0), nBytes, abKey(0), DECRYPT)
        Debug.Print "P'=" & cnvHexStrFromBytes(abBlock)
        Debug.Assert (StrConv(abBlock, vbUnicode) = StrConv(abPlain, vbUnicode))

End Sub

Public Sub V_Test_AES128_BytesMode()
    Debug.Print "Testing AES128_BytesMode ..."
        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 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=" & cnvHexStrFromBytes(abData)
        ' Encrypt in one-off process
        nRet = AES128_BytesMode(abResult(0), abData(0), nDataLen, abKey(0), _
            ENCRYPT, "CBC", abInitV(0))
        Debug.Print "CT=" & cnvHexStrFromBytes(abResult)
        Debug.Print "OK=" & sCorrect
    
        ' Now decrypt back
        nRet = AES128_BytesMode(abData(0), abResult(0), nDataLen, abKey(0), _
            DECRYPT, "CBC", abInitV(0))
        strOutput = StrConv(abData(), vbUnicode)
        Debug.Print "P'=" & strOutput
        
        ' Check
        Debug.Assert (strOutput = strInput)

End Sub

Public Sub V_Test_AES128_File()
    Debug.Print "Testing AES128_File ..."
    Const MY_PATH As String = ""
    Dim strFileOut As String, strFileIn As String, strFileChk As String
    Dim nRet As Long
    Dim abKey() As Byte
    
    ' Construct full path names to files
    strFileIn = MY_PATH & "now.txt"
    strFileOut = MY_PATH & "now.aes128.enc.dat"
    strFileChk = MY_PATH & "now.aes128.chk.txt"
    
    ' Convert key to byte array
    abKey = cnvBytesFromHexStr("0123456789ABCDEFF0E1D2C3B4A59687")
    ' Encrypt plaintext file to cipher
    nRet = AES128_File(strFileOut, strFileIn, abKey(0), ENCRYPT, "ECB", 0)
    If nRet <> 0 Then
        Debug.Print "Error " & nRet & ": " & apiErrorLookup(nRet)
    End If
    
    ' Now decrypt it
    nRet = AES128_File(strFileChk, strFileOut, abKey(0), DECRYPT, "ECB", 0)
    If nRet <> 0 Then
        Debug.Print "Error " & nRet & ": " & apiErrorLookup(nRet)
    End If

End Sub

Public Sub V_Test_AES128_FileExt()
    Debug.Print "Testing AES128_FileExt ..."
    
End Sub

Public Sub V_Test_AES128_FileHex()
    Debug.Print "Testing AES128_FileHex ..."
        Dim nRet As Long
        nRet = AES128_FileHex("bigfile.cbc", "bigfile.dat", _
            "fedcba9876543210fedcba9876543210", _
            ENCRYPT, "CBC", "0123456789abcdef0123456789abcdef")
        If nRet <> 0 Then
            Debug.Print "AES128_FileHex failed: " & apiErrorLookup(nRet)
        Else
            Debug.Print "AES128_FileHex encrypted file OK"
        End If

End Sub

Public Sub V_Test_AES128_Hex()
    Debug.Print "Testing AES128_Hex ..."
        Dim nRet As Long
        Dim strOutput As String
        Dim strInput As String
        Dim strHexKey As String
        Dim sPlain As String
        Dim sCipher As String
        
        'FIPS-197
        'C.1 AES-128 (Nk=4, Nr=10)
        'PLAINTEXT: 00112233445566778899aabbccddeeff
        'KEY: 000102030405060708090a0b0c0d0e0f
        strHexKey = "000102030405060708090a0b0c0d0e0f"
        sPlain = "00112233445566778899aabbccddeeff"
        sCipher = "69c4e0d86a7b0430d8cdb78070b4c55a"
        
        strInput = sPlain
        ' Set strOutput to be same length as strInput
        strOutput = String(Len(strInput), " ")
        
        Debug.Print "KY=" & strHexKey
        Debug.Print "PT=" & strInput
        ' Encrypt in one-off process
        nRet = AES128_Hex(strOutput, strInput, strHexKey, ENCRYPT)
        Debug.Print "CT=" & strOutput & nRet
        Debug.Print "OK=" & sCipher
        Debug.Assert (strOutput = sCipher)
        
        ' Now decrypt back to plain text
        strInput = strOutput
        nRet = AES128_Hex(strOutput, strInput, strHexKey, DECRYPT)
        Debug.Print "P'=" & strOutput; nRet
        Debug.Assert (strOutput = sPlain)

End Sub

Public Sub V_Test_AES128_HexMode()
    Debug.Print "Testing AES128_HexMode ..."
        Dim nRet As Long
        Dim strOutput As String
        Dim strInput As String
        Dim strHexKey As String
        Dim sPlain As String
        Dim sCipher As String
        Dim strHexIV As String
    'Case #1: Encrypting 16 bytes (1 block) using AES-CBC with 128-bit key
    'Key       : 0x06a9214036b8a15b512e03d534120006
    'IV        : 0x3dafba429d9eb430b422da802c9fac41
    'Plaintext : "Single block msg"
    'Ciphertext: 0xe353779c1079aeb82708942dbe77181a
    
        strHexKey = "06a9214036b8a15b512e03d534120006"
        strHexIV = "3dafba429d9eb430b422da802c9fac41"
        sPlain = cnvHexStrFromString("Single block msg")
        sCipher = "e353779c1079aeb82708942dbe77181a"
        
        strInput = sPlain
        ' Set strOutput to be same length as strInput
        strOutput = String(Len(strInput), " ")
        
        Debug.Print "KY=" & strHexKey
        Debug.Print "IV=" & strHexIV
        Debug.Print "PT=" & strInput
        ' Encrypt in one-off process
        nRet = AES128_HexMode(strOutput, strInput, strHexKey, ENCRYPT, "CBC", strHexIV)
        Debug.Print "CT=" & strOutput; nRet
        Debug.Print "OK=" & sCipher
        Debug.Assert (strOutput = sCipher)
        
        ' Decrypt to check
        strInput = strOutput
        nRet = AES128_HexMode(strOutput, strInput, strHexKey, DECRYPT, "CBC", strHexIV)
        Debug.Print "P'=" & strOutput; nRet
        Debug.Print "OK=" & sPlain
        Debug.Assert (strOutput = sPlain)
        
    ' Case #4: Encrypting 64 bytes (4 blocks) using AES-CBC with 128-bit key
    ' Key       : 0x56e47a38c5598974bc46903dba290349
    ' IV        : 0x8ce82eefbea0da3c44699ed7db51b7d9
    ' Plaintext : 0xa0a1a2a3a4a5a6a7a8a9aaabacadaeaf
    '               b0b1b2b3b4b5b6b7b8b9babbbcbdbebf
    '               c0c1c2c3c4c5c6c7c8c9cacbcccdcecf
    '               d0d1d2d3d4d5d6d7d8d9dadbdcdddedf
    ' Ciphertext: 0xc30e32ffedc0774e6aff6af0869f71aa
    '               0f3af07a9a31a9c684db207eb0ef8e4e
    '               35907aa632c3ffdf868bb7b29d3d46ad
    '               83ce9f9a102ee99d49a53e87f4c3da55
        
        strHexKey = "56e47a38c5598974bc46903dba290349"
        strHexIV = "8ce82eefbea0da3c44699ed7db51b7d9"
        sPlain = "a0a1a2a3a4a5a6a7a8a9aaabacadaeaf" _
            & "b0b1b2b3b4b5b6b7b8b9babbbcbdbebf" _
            & "c0c1c2c3c4c5c6c7c8c9cacbcccdcecf" _
            & "d0d1d2d3d4d5d6d7d8d9dadbdcdddedf"
        sCipher = "c30e32ffedc0774e6aff6af0869f71aa" _
            & "0f3af07a9a31a9c684db207eb0ef8e4e" _
            & "35907aa632c3ffdf868bb7b29d3d46ad" _
            & "83ce9f9a102ee99d49a53e87f4c3da55"
            
        strInput = sPlain
        ' Set strOutput to be same length as strInput
        strOutput = String(Len(strInput), " ")
        
        Debug.Print "KY=" & strHexKey
        Debug.Print "IV=" & strHexIV
        Debug.Print "PT=" & strInput
        ' Encrypt in one-off process
        nRet = AES128_HexMode(strOutput, strInput, strHexKey, ENCRYPT, "CBC", strHexIV)
        Debug.Print "CT=" & strOutput; nRet
        Debug.Print "OK=" & sCipher
        Debug.Assert (strOutput = sCipher)
    
        ' Decrypt to check
        strInput = strOutput
        nRet = AES128_HexMode(strOutput, strInput, strHexKey, DECRYPT, "CBC", strHexIV)
        Debug.Print "P'=" & strOutput; nRet
        Debug.Print "OK=" & sPlain
        Debug.Assert (strOutput = sPlain)

End Sub

Public Sub V_Test_AES128_InitError()
    Debug.Print "Testing AES128_InitError ..."
        Dim hContext As Long
        Dim nRet As Long
        
        ' Try to initialise with an invalid key
        hContext = AES128_InitHex("THIS IS NOT HEX!", ENCRYPT, _
            "CBC", "0123456789abcdef0123456789abcdef")
        If hContext = 0 Then
            nRet = AES128_InitError()
            Debug.Print "AES128_InitHex failed (" & apiErrorLookup(nRet) & ")"
        End If
        
        ' Try with an invalid mode
        hContext = AES128_InitHex("8A05FC5E095AF4848A08D328D3688E3D", _
            ENCRYPT, "XXX", "0123456789abcdef0123456789abcdef")
        If hContext = 0 Then
            nRet = AES128_InitError()
            Debug.Print "AES128_InitHex failed (" & apiErrorLookup(nRet) & ")"
        End If

End Sub

Public Sub V_Test_AES128_Update()
    Debug.Print "Testing AES128_Update ..."
        Dim nRet As Long
        Dim hContext As Long
        Dim abBlock() As Byte
        Dim abKey() As Byte
        Dim abCorrect() As Byte
        Dim j As Integer
        
    ' File: ecb_d_m.txt
    ' KEYSIZE=128 I=2
    ' KEY=A7BC3BD0EABD9EBA981E23E6FFC9C9C2
    ' CT=E3FD51123B48A2E2AB1DB29894202222
    ' PT=877B88A77AEF04F05546539E17259F53
         ' Convert to Byte format
        abKey = cnvBytesFromHexStr("A7BC3BD0EABD9EBA981E23E6FFC9C9C2")
        abBlock = cnvBytesFromHexStr("E3FD51123B48A2E2AB1DB29894202222")
        abCorrect = cnvBytesFromHexStr("877B88A77AEF04F05546539E17259F53")
        
        Debug.Print "AES Monte Carlo ECB Mode Decrypt:"
        Debug.Print "KY=" & cnvHexStrFromBytes(abKey)
        Debug.Print "CT=" & cnvHexStrFromBytes(abBlock)
        
        hContext = AES128_Init(abKey(0), DECRYPT, "ECB", 0)
        If hContext = 0 Then
            MsgBox "Failed to set context", vbCritical
            Exit Sub
        End If
        ' Do 10,000 times
        For j = 0 To 9999
            nRet = AES128_Update(hContext, abBlock(0), 16)
        Next
        Debug.Print "PT=" & cnvHexStrFromBytes(abBlock)
        Debug.Print "OK=" & cnvHexStrFromBytes(abCorrect)
        nRet = AES128_Final(hContext)
        
        Debug.Assert (StrConv(abCorrect, vbUnicode) = StrConv(abBlock, vbUnicode))

End Sub

Public Sub V_Test_AES128_UpdateHex()
    Debug.Print "Testing AES128_UpdateHex ..."
    Dim nRet As Long
    Dim hContext As Long
    Dim sBlock As String
    Dim strHexKey As String
    Dim strIV As String
    Dim sNext As String
    Dim sLast As String
    Dim sCorrect As String
    Dim j As Integer
    
    ' cbc_e_m.txt
    ' KEYSIZE=128 I=2
    ' KEY=93286764A85146730E641888DB34EB47
    ' IV=192D9B3AA10BB2F7846CCBA0085C657A
    ' PT=983BF6F5A6DFBCDAA19370666E83A99A
    ' CT=40D8DAF6D1FDA0A073B3BD18B7695D2E
    
    strHexKey = "93286764A85146730E641888DB34EB47"
    strIV = "192D9B3AA10BB2F7846CCBA0085C657A"
    sBlock = "983BF6F5A6DFBCDAA19370666E83A99A"
    sCorrect = "40D8DAF6D1FDA0A073B3BD18B7695D2E"
    
    Debug.Print "AES Monte Carlo CBC Mode Encrypt:"
    Debug.Print "KY=" & strHexKey
    Debug.Print "IV=" & strIV
    Debug.Print "PT=" & sBlock
    
    hContext = AES128_InitHex(strHexKey, ENCRYPT, "CBC", strIV)
    If hContext = 0 Then
        MsgBox "Failed to set context", vbCritical
        Exit Sub
    End If
    ' Do 10,000 times
    sNext = sBlock
    For j = 0 To 9999
        sBlock = sNext
        nRet = AES128_UpdateHex(hContext, sBlock)
        If j = 0 Then
            sNext = strIV
        Else
            sNext = sLast
        End If
        sLast = sBlock
    Next
    Debug.Print "CT=" & sBlock
    Debug.Print "OK=" & sCorrect
    nRet = AES128_Final(hContext)
    
    Debug.Assert (sCorrect = sBlock)

End Sub

Public Sub V_Test_AES192_B64Mode()
    Debug.Print "Testing AES192_B64Mode ..."
    Dim nRet As Long
    Dim strOutput As String
    Dim strInput As String
    Dim strKey As String
    Dim strIV As String
    Dim bEncrypt As Boolean
    Dim sCorrect As String
    
    strInput = "oKGio6SlpqeoqaqrrK2ur7CxsrO0tba3uLm6u7y" _
    & "9vr/AwcLDxMXGx8jJysvMzc7P0NHS09TV1tfY2drb3N3e3w=="
    strKey = "VuR6OMVZiXS8RpA9uikDSQapIUA2uKFb"
    strIV = "jOgu776g2jxEaZ7X21G32Q=="
    sCorrect = "c4I3A2393p3aM3T6GCYAxTjZGHoCmXJdCn/b6" _
    & "ETXdXgVOeQBtVl8u/qDbv0i2ZjSFgXY3zQGIkF7kRRnteUaEg=="
    
    ' Set strOutput to be same length as strInput
    strOutput = String(Len(strInput), " ")
    
    Debug.Print "KY=" & strKey
    Debug.Print "IV=" & strIV
    Debug.Print "PT=" & strInput
    nRet = AES192_B64Mode(strOutput, strInput, strKey, ENCRYPT, "CBC", strIV)
    Debug.Print "CT=" & strOutput; nRet
    Debug.Print "OK=" & sCorrect
    
    strInput = strOutput
    nRet = AES192_B64Mode(strOutput, strInput, strKey, DECRYPT, "CBC", strIV)
    Debug.Print "P'=" & strOutput; nRet

End Sub

Public Sub V_Test_AES192_Bytes()
    Debug.Print "Testing AES192_Bytes ..."
        Dim nRet As Long
        Dim strHexKey As String
        Dim sPlain As String
        Dim sCipher As String
        Dim abBlock() As Byte
        Dim abKey() As Byte
        Dim abPlain() As Byte
        Dim abCipher() As Byte
        Dim nBytes As Long
        
        'FIPS-197
        'C.2 AES-192 (Nk=6, Nr=12)
        'PLAINTEXT: 00112233445566778899aabbccddeeff
        'KEY: 000102030405060708090a0b0c0d0e0f1011121314151617
        strHexKey = "000102030405060708090a0b0c0d0e0f1011121314151617"
        sPlain = "00112233445566778899aabbccddeeff"
        sCipher = "dda97ca4864cdfe06eaf70a0ec0d7191"
        
        ' Convert input to bytes
        abKey = cnvBytesFromHexStr(strHexKey)
        abPlain = cnvBytesFromHexStr(sPlain)
        abCipher = cnvBytesFromHexStr(sCipher)
        
        abBlock = abPlain
        nBytes = UBound(abBlock) - LBound(abBlock) + 1
        Debug.Print "KY=" & cnvHexStrFromBytes(abKey)
        Debug.Print "PT=" & cnvHexStrFromBytes(abBlock)
        ' Encrypt in one-off process
        nRet = AES192_Bytes(abBlock(0), abBlock(0), nBytes, abKey(0), ENCRYPT)
        Debug.Print "CT=" & cnvHexStrFromBytes(abBlock)
        Debug.Print "OK=" & cnvHexStrFromBytes(abCipher)
        Debug.Assert (StrConv(abBlock, vbUnicode) = StrConv(abCipher, vbUnicode))
        
        ' Now decrypt back to plain text
        nRet = AES192_Bytes(abBlock(0), abBlock(0), nBytes, abKey(0), DECRYPT)
        Debug.Print "P'=" & cnvHexStrFromBytes(abBlock)
        Debug.Assert (StrConv(abBlock, vbUnicode) = StrConv(abPlain, vbUnicode))

End Sub

Public Sub V_Test_AES192_BytesMode()
    Debug.Print "Testing AES192_BytesMode ..."
        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 nDataLen As Long
    
        ' Set up input in byte arrays
        strInput = "Now is the time for all good men"
        sCorrect = "4BABDC251410549C57390F7FA3F26366F9AC1FABD1354ECA2265F475A2C3D5AF"
        abKey = cnvBytesFromHexStr("000102030405060708090a0b0c0d0e0f1011121314151617")
        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=" & cnvHexStrFromBytes(abData)
        ' Encrypt in one-off process
        nRet = AES192_BytesMode(abResult(0), abData(0), nDataLen, abKey(0), _
            ENCRYPT, "CBC", abInitV(0))
        Debug.Print "CT=" & cnvHexStrFromBytes(abResult)
        Debug.Print "OK=" & sCorrect
        Debug.Assert (sCorrect = cnvHexStrFromBytes(abResult))
    
        ' Now decrypt back
        nRet = AES192_BytesMode(abData(0), abResult(0), nDataLen, abKey(0), _
            DECRYPT, "CBC", abInitV(0))
        strOutput = StrConv(abData(), vbUnicode)
        Debug.Print "P'=" & strOutput
        
        ' Check
        Debug.Assert (strOutput = strInput)

End Sub

Public Sub V_Test_AES192_File()
    Debug.Print "Testing AES192_File ..."
        Const MY_PATH As String = ""
        Dim strFileOut As String, strFileIn As String, strFileChk As String
        Dim nRet As Long
        Dim abKey() As Byte
    
        ' Construct full path names to files
        strFileIn = MY_PATH & "now.txt"
        strFileOut = MY_PATH & "now.aes192.enc.data"
        strFileChk = MY_PATH & "now.aes192.chk.txt"
    
        ' Convert key to byte array
        abKey = cnvBytesFromHexStr("000102030405060708090a0b0c0d0e0f1011121314151617")
        ' Encrypt plaintext file to cipher
        nRet = AES192_File(strFileOut, strFileIn, abKey(0), ENCRYPT, "ECB", 0)
        If nRet <> 0 Then
            Debug.Print "Error " & nRet & ": " & apiErrorLookup(nRet)
        End If
    
        ' Now decrypt it
        nRet = AES192_File(strFileChk, strFileOut, abKey(0), DECRYPT, "ECB", 0)
        If nRet <> 0 Then
            Debug.Print "Error " & nRet & ": " & apiErrorLookup(nRet)
        End If

End Sub

Public Sub V_Test_AES192_FileExt()
    Debug.Print "Testing AES192_FileExt ..."
    
End Sub

Public Sub V_Test_AES192_FileHex()
    Debug.Print "Testing AES192_FileHex ..."
        Dim nRet As Long
        nRet = AES192_FileHex("bigfile.cbc", "bigfile.dat", _
            "000102030405060708090a0b0c0d0e0f1011121314151617", _
            ENCRYPT, "CBC", "0123456789abcdef0123456789abcdef")
        If nRet <> 0 Then
            Debug.Print "AES192_FileHex failed: " & apiErrorLookup(nRet)
        Else
            Debug.Print "AES192_FileHex encrypted file OK"
        End If

End Sub

Public Sub V_Test_AES192_Hex()
    Debug.Print "Testing AES192_Hex ..."
        Dim nRet As Long
        Dim strOutput As String
        Dim strInput As String
        Dim strHexKey As String
        Dim sPlain As String
        Dim sCipher As String
        
        'FIPS-197
        'C.2 AES-192 (Nk=6, Nr=12)
        'PLAINTEXT: 00112233445566778899aabbccddeeff
        'KEY: 000102030405060708090a0b0c0d0e0f1011121314151617
        strHexKey = "000102030405060708090a0b0c0d0e0f1011121314151617"
        sPlain = "00112233445566778899aabbccddeeff"
        sCipher = "dda97ca4864cdfe06eaf70a0ec0d7191"
        
        strInput = sPlain
        ' Set strOutput to be same length as strInput
        strOutput = String(Len(strInput), " ")
        
        Debug.Print "KY=" & strHexKey
        Debug.Print "PT=" & strInput
        ' Encrypt in one-off process
        nRet = AES192_Hex(strOutput, strInput, strHexKey, ENCRYPT)
        Debug.Print "CT=" & strOutput; nRet
        Debug.Print "OK=" & sCipher
        
        ' Now decrypt back to plain text
        strInput = strOutput
        nRet = AES192_Hex(strOutput, strInput, strHexKey, DECRYPT)
        Debug.Print "P'=" & strOutput; nRet

End Sub

Public Sub V_Test_AES192_HexMode()
    Debug.Print "Testing AES192_HexMode ..."
        Dim nRet As Long
        Dim strOutput As String
        Dim strInput As String
        Dim strHexKey As String
        Dim sPlain As String
        Dim sCipher As String
        Dim strHexIV As String
        
    ' Encrypting 64 bytes (4 blocks) using AES-CBC with 192-bit key
        
        strHexKey = "56e47a38c5598974bc46903dba29034906a9214036b8a15b"
        strHexIV = "8ce82eefbea0da3c44699ed7db51b7d9"
        sPlain = "a0a1a2a3a4a5a6a7a8a9aaabacadaeaf" _
            & "b0b1b2b3b4b5b6b7b8b9babbbcbdbebf" _
            & "c0c1c2c3c4c5c6c7c8c9cacbcccdcecf" _
            & "d0d1d2d3d4d5d6d7d8d9dadbdcdddedf"
        sCipher = "738237036dfdde9dda3374fa182600c5" _
            & "38d9187a0299725d0a7fdbe844d77578" _
            & "1539e401b5597cbbfa836efd22d998d2" _
            & "1605d8df340622417b911467b5e51a12" _
            
        strInput = sPlain
        ' Set strOutput to be same length as strInput
        strOutput = String(Len(strInput), " ")
        
        Debug.Print "KY=" & strHexKey
        Debug.Print "IV=" & strHexIV
        Debug.Print "PT=" & strInput
        ' Encrypt in one-off process
        nRet = AES192_HexMode(strOutput, strInput, strHexKey, ENCRYPT, "CBC", strHexIV)
        Debug.Print "CT=" & strOutput; nRet
        Debug.Print "OK=" & sCipher
        Debug.Assert (strOutput = sCipher)
    
        ' Decrypt to check
        strInput = strOutput
        nRet = AES192_HexMode(strOutput, strInput, strHexKey, DECRYPT, "CBC", strHexIV)
        Debug.Print "P'=" & strOutput; nRet
        Debug.Print "OK=" & sPlain
        Debug.Assert (strOutput = sPlain)

End Sub

Public Sub V_Test_AES192_InitError()
    Debug.Print "Testing AES192_InitError ..."
        Dim hContext As Long
        Dim nRet As Long
        
        ' Try to initialise with an invalid key
        hContext = AES192_InitHex("THIS IS NOT HEX!", ENCRYPT, _
            "CBC", "0123456789abcdef0123456789abcdef")
        If hContext = 0 Then
            nRet = AES192_InitError()
            Debug.Print "AES192_InitHex failed (" & apiErrorLookup(nRet) & ")"
        End If
        
        ' Try with an invalid mode
        hContext = AES192_InitHex("000102030405060708090a0b0c0d0e0f1011121314151617", _
            ENCRYPT, "XXX", "0123456789abcdef0123456789abcdef")
        If hContext = 0 Then
            nRet = AES192_InitError()
            Debug.Print "AES192_InitHex failed (" & apiErrorLookup(nRet) & ")"
        End If

End Sub

Public Sub V_Test_AES192_Update()
    Debug.Print "Testing AES192_Update ..."
        Dim nRet As Long
        Dim hContext As Long
        Dim abBlock() As Byte
        Dim abKey() As Byte
        Dim abCorrect() As Byte
        Dim j As Integer
        
    ' File: ecb_d_m.txt
    ' KEYSIZE=192 I=2
    ' KEY=EF334C87288C43DE84E276D5CCD586228C8EA3A264D2DB0E
    ' CT=CC01684BE9B29ED01EA7923E7D2380AA
    ' PT=8726B4E66D6B8FBAA22D42981A5A40CC
         ' Convert to Byte format
        abKey = cnvBytesFromHexStr("EF334C87288C43DE84E276D5CCD586228C8EA3A264D2DB0E")
        abBlock = cnvBytesFromHexStr("CC01684BE9B29ED01EA7923E7D2380AA")
        abCorrect = cnvBytesFromHexStr("8726B4E66D6B8FBAA22D42981A5A40CC")
        
        Debug.Print "AES Monte Carlo ECB Mode Decrypt:"
        Debug.Print "KY=" & cnvHexStrFromBytes(abKey)
        Debug.Print "CT=" & cnvHexStrFromBytes(abBlock)
        
        hContext = AES192_Init(abKey(0), DECRYPT, "ECB", 0)
        If hContext = 0 Then
            MsgBox "Failed to set context", vbCritical
            Exit Sub
        End If
        ' Do 10,000 times
        For j = 0 To 9999
            nRet = AES192_Update(hContext, abBlock(0), 16)
        Next
        Debug.Print "PT=" & cnvHexStrFromBytes(abBlock)
        Debug.Print "OK=" & cnvHexStrFromBytes(abCorrect)
        nRet = AES192_Final(hContext)
        
        Debug.Assert (StrConv(abCorrect, vbUnicode) = StrConv(abBlock, vbUnicode))

End Sub

Public Sub V_Test_AES192_UpdateHex()
    Debug.Print "Testing AES192_UpdateHex ..."
        Dim nRet As Long
        Dim hContext As Long
        Dim sBlock As String
        Dim strHexKey As String
        Dim strIV As String
        Dim sNext As String
        Dim sLast As String
        Dim sCorrect As String
        Dim j As Integer
      
    ' cbc_e_m.txt
    ' KEYSIZE=192 I=2
    ' KEY=74D3414C2374367BFD4560CED3172B0E57571D88A2E13874
    ' IV=869C061BE9CFEAB5D285B0724A9A8970
    ' PT=C6FB25A188CF7F3F24B07896C0C76D90
    ' CT=9E58A52B3840DBE16E8063A18220FEE4
    
        
        strHexKey = "74D3414C2374367BFD4560CED3172B0E57571D88A2E13874"
        strIV = "869C061BE9CFEAB5D285B0724A9A8970"
        sBlock = "C6FB25A188CF7F3F24B07896C0C76D90"
        sCorrect = "9E58A52B3840DBE16E8063A18220FEE4"
        
        Debug.Print "AES Monte Carlo CBC Mode Encrypt:"
        Debug.Print "KY=" & strHexKey
        Debug.Print "IV=" & strIV
        Debug.Print "PT=" & sBlock
        
        hContext = AES192_InitHex(strHexKey, ENCRYPT, "CBC", strIV)
        If hContext = 0 Then
            MsgBox "Failed to set context", vbCritical
            Exit Sub
        End If
        ' Do 10,000 times
        sNext = sBlock
        For j = 0 To 9999
            sBlock = sNext
            nRet = AES192_UpdateHex(hContext, sBlock)
            If j = 0 Then
                sNext = strIV
            Else
                sNext = sLast
            End If
            sLast = sBlock
        Next
        Debug.Print "CT=" & sBlock
        Debug.Print "OK=" & sCorrect
        nRet = AES192_Final(hContext)
        
        Debug.Assert (sCorrect = sBlock)

End Sub

Public Sub V_Test_AES256_B64Mode()
    Debug.Print "Testing AES256_B64Mode ..."
    Dim nRet As Long
    Dim strOutput As String
    Dim strInput As String
    Dim strKey As String
    Dim strIV As String
    Dim bEncrypt As Boolean
    Dim sCorrect As String
    
    strInput = "oKGio6SlpqeoqaqrrK2ur7CxsrO0tba3uLm6u7y9vr/" _
    & "AwcLDxMXGx8jJysvMzc7P0NHS09TV1tfY2drb3N3e3w=="
    strKey = "VuR6OMVZiXS8RpA9uikDSQapIUA2uKFbUS4D1TQSAAY="
    strIV = "jOgu776g2jxEaZ7X21G32Q=="
    sCorrect = "KECaKYK9LPfONDp9Q/aSf9uexTK7pWnuyS5XognE/" _
    & "bpZrboFpchUaU3cn3mRwBY05yvrT+AjbLOxGaRjiR40bw=="
    
    ' Set strOutput to be same length as strInput
    strOutput = String(Len(strInput), " ")
    
    Debug.Print "KY=" & strKey
    Debug.Print "IV=" & strIV
    Debug.Print "PT=" & strInput
    nRet = AES256_B64Mode(strOutput, strInput, strKey, ENCRYPT, "CBC", strIV)
    Debug.Print "CT=" & strOutput; nRet
    Debug.Print "OK=" & sCorrect
    
    strInput = strOutput
    nRet = AES256_B64Mode(strOutput, strInput, strKey, DECRYPT, "CBC", strIV)
    Debug.Print "P'=" & strOutput; nRet

End Sub

Public Sub V_Test_AES256_Bytes()
    Debug.Print "Testing AES256_Bytes ..."
        Dim nRet As Long
        Dim strHexKey As String
        Dim sPlain As String
        Dim sCipher As String
        Dim abBlock() As Byte
        Dim abKey() As Byte
        Dim abPlain() As Byte
        Dim abCipher() As Byte
        Dim nBytes As Long
        
    'FIPS-197
    'C.3 AES-256 (Nk=8, Nr=14)
    'PLAINTEXT: 00112233445566778899aabbccddeeff
    'KEY: 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
    ' round[14].output 8ea2b7ca516745bfeafc49904b496089
    
        strHexKey = _
        "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f"
        sPlain = "00112233445566778899aabbccddeeff"
        sCipher = "8ea2b7ca516745bfeafc49904b496089"
        
        ' Convert input to bytes
        abKey = cnvBytesFromHexStr(strHexKey)
        abPlain = cnvBytesFromHexStr(sPlain)
        abCipher = cnvBytesFromHexStr(sCipher)
        
        abBlock = abPlain
        nBytes = UBound(abBlock) - LBound(abBlock) + 1
        Debug.Print "KY=" & cnvHexStrFromBytes(abKey)
        Debug.Print "PT=" & cnvHexStrFromBytes(abBlock)
        ' Encrypt in one-off process
        nRet = AES256_Bytes(abBlock(0), abBlock(0), nBytes, abKey(0), ENCRYPT)
        Debug.Print "CT=" & cnvHexStrFromBytes(abBlock)
        Debug.Print "OK=" & cnvHexStrFromBytes(abCipher)
        Debug.Assert (StrConv(abBlock, vbUnicode) = StrConv(abCipher, vbUnicode))
        
        ' Now decrypt back to plain text
        nRet = AES256_Bytes(abBlock(0), abBlock(0), nBytes, abKey(0), DECRYPT)
        Debug.Print "P'=" & cnvHexStrFromBytes(abBlock)
        Debug.Assert (StrConv(abBlock, vbUnicode) = StrConv(abPlain, vbUnicode))

End Sub

Public Sub V_Test_AES256_BytesMode()
    Debug.Print "Testing AES256_BytesMode ..."
        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 nDataLen As Long
    
        ' Set up input in byte arrays
        strInput = "Now is the time for all good men"
        sCorrect = "36161E5B4B62401A5B57996F7D6839D34E181930DEBBAEBE84AE01139E9581A6"
        abKey = _
        cnvBytesFromHexStr("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f")
        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=" & cnvHexStrFromBytes(abData)
        ' Encrypt in one-off process
        nRet = AES256_BytesMode(abResult(0), abData(0), nDataLen, abKey(0), _
            ENCRYPT, "CBC", abInitV(0))
        Debug.Print "CT=" & cnvHexStrFromBytes(abResult)
        Debug.Print "OK=" & sCorrect
        Debug.Assert (sCorrect = cnvHexStrFromBytes(abResult))
    
        ' Now decrypt back
        nRet = AES256_BytesMode(abData(0), abResult(0), nDataLen, abKey(0), _
            DECRYPT, "CBC", abInitV(0))
        strOutput = StrConv(abData(), vbUnicode)
        Debug.Print "P'=" & strOutput
        
        ' Check
        Debug.Assert (strOutput = strInput)

End Sub

Public Sub V_Test_AES256_File()
    Debug.Print "Testing AES256_File ..."
        Const MY_PATH As String = ""
        Dim strFileOut As String, strFileIn As String, strFileChk As String
        Dim nRet As Long
        Dim abKey() As Byte
    
        ' Construct full path names to files
        strFileIn = MY_PATH & "now.txt"
        strFileOut = MY_PATH & "now.aes256.enc.dat"
        strFileChk = MY_PATH & "now.aes256.chk.txt"
    
        ' Convert key to byte array
        abKey = _
    cnvBytesFromHexStr("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f")
        ' Encrypt plaintext file to cipher
        nRet = AES256_File(strFileOut, strFileIn, abKey(0), ENCRYPT, "ECB", 0)
        If nRet <> 0 Then
            Debug.Print "Error " & nRet & ": " & apiErrorLookup(nRet)
        End If
    
        ' Now decrypt it
        nRet = AES256_File(strFileChk, strFileOut, abKey(0), DECRYPT, "ECB", 0)
        If nRet <> 0 Then
            Debug.Print "Error " & nRet & ": " & apiErrorLookup(nRet)
        End If

End Sub

Public Sub V_Test_AES256_FileExt()
    Debug.Print "Testing AES256_FileExt ..."
    
End Sub

Public Sub V_Test_AES256_FileHex()
    Debug.Print "Testing AES256_FileHex ..."
    Dim nRet As Long
    nRet = AES256_FileHex("bigfile.cbc", "bigfile.dat", _
        "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", _
        ENCRYPT, "CBC", "0123456789abcdef0123456789abcdef")
    If nRet <> 0 Then
        Debug.Print "AES256_FileHex failed: " & apiErrorLookup(nRet)
    Else
        Debug.Print "AES256_FileHex encrypted file OK"
    End If

End Sub

Public Sub V_Test_AES256_Hex()
    Debug.Print "Testing AES256_Hex ..."
        Dim nRet As Long
        Dim strOutput As String
        Dim strInput As String
        Dim strHexKey As String
        Dim sPlain As String
        Dim sCipher As String
        
    'FIPS-197
    'C.3 AES-256 (Nk=8, Nr=14)
    'PLAINTEXT: 00112233445566778899aabbccddeeff
    'KEY: 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
        strHexKey = _
        "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f"
        sPlain = "00112233445566778899aabbccddeeff"
        sCipher = "8EA2B7CA516745BFEAFC49904B496089"
        
        strInput = sPlain
        ' Set strOutput to be same length as strInput
        strOutput = String(Len(strInput), " ")
        
        Debug.Print "KY=" & strHexKey
        Debug.Print "PT=" & strInput
        ' Encrypt in one-off process
        nRet = AES256_Hex(strOutput, strInput, strHexKey, ENCRYPT)
        Debug.Print "CT=" & strOutput; nRet
        Debug.Print "OK=" & sCipher
        Debug.Assert (strOutput = sCipher)
        
        ' Now decrypt back to plain text
        strInput = strOutput
        nRet = AES256_Hex(strOutput, strInput, strHexKey, DECRYPT)
        Debug.Print "P'=" & strOutput; nRet
        Debug.Assert (strOutput = sPlain)

End Sub

Public Sub V_Test_AES256_HexMode()
    Debug.Print "Testing AES256_HexMode ..."
        Dim nRet As Long
        Dim strOutput As String
        Dim strInput As String
        Dim strHexKey As String
        Dim sPlain As String
        Dim sCipher As String
        Dim strHexIV As String
        
    ' Encrypting 64 bytes (4 blocks) using AES-CBC with 256-bit key
        
        strHexKey = "56e47a38c5598974bc46903dba29034906a9214036b8a15b512e03d534120006"
        strHexIV = "8ce82eefbea0da3c44699ed7db51b7d9"
        sPlain = "a0a1a2a3a4a5a6a7a8a9aaabacadaeaf" _
            & "b0b1b2b3b4b5b6b7b8b9babbbcbdbebf" _
            & "c0c1c2c3c4c5c6c7c8c9cacbcccdcecf" _
            & "d0d1d2d3d4d5d6d7d8d9dadbdcdddedf"
        sCipher = "28409A2982BD2CF7CE343A7D43F6927F" _
            & "DB9EC532BBA569EEC92E57A209C4FDBA" _
            & "59ADBA05A5C854694DDC9F7991C01634" _
            & "E72BEB4FE0236CB3B119A463891E346F"
            
        strInput = sPlain
        ' Set strOutput to be same length as strInput
        strOutput = String(Len(strInput), " ")
        
        Debug.Print "KY=" & strHexKey
        Debug.Print "IV=" & strHexIV
        Debug.Print "PT=" & strInput
        ' Encrypt in one-off process
        nRet = AES256_HexMode(strOutput, strInput, strHexKey, ENCRYPT, "CBC", strHexIV)
        Debug.Print "CT=" & strOutput; nRet
        Debug.Print "OK=" & sCipher
        Debug.Assert (strOutput = sCipher)
    
        ' Decrypt to check
        strInput = strOutput
        nRet = AES256_HexMode(strOutput, strInput, strHexKey, DECRYPT, "CBC", strHexIV)
        Debug.Print "P'=" & strOutput; nRet
        Debug.Print "OK=" & sPlain
        Debug.Assert (strOutput = sPlain)

End Sub

Public Sub V_Test_AES256_InitError()
    Debug.Print "Testing AES256_InitError ..."
        Dim hContext As Long
        Dim nRet As Long
        
        ' Try to initialise with an invalid key
        hContext = AES256_InitHex("THIS IS NOT HEX!", ENCRYPT, _
            "CBC", "0123456789abcdef0123456789abcdef")
        If hContext = 0 Then
            nRet = AES192_InitError()
            Debug.Print "AES192_InitHex failed (" & apiErrorLookup(nRet) & ")"
        End If
        
        ' Try with an invalid mode
        hContext = AES256_InitHex("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", _
            ENCRYPT, "XXX", "0123456789abcdef0123456789abcdef")
        If hContext = 0 Then
            nRet = AES192_InitError()
            Debug.Print "AES192_InitHex failed (" & apiErrorLookup(nRet) & ")"
        End If

End Sub

Public Sub V_Test_AES256_Update()
    Debug.Print "Testing AES256_Update ..."
        Dim nRet As Long
        Dim hContext As Long
        Dim abBlock() As Byte
        Dim abKey() As Byte
        Dim abCorrect() As Byte
        Dim j As Integer
        
    ' File: ecb_d_m.txt
    ' KEYSIZE=256 I=2
    ' KEY=2447EC44111548FBB670B98F182D5DEE109BF5F30D9464ED411F18A63C53A998
    ' CT=15173A0EB65F5CC05E704EFE61D9E346
    ' PT=85F083ACC676D91EDD1ABFB43935237A
        ' Convert to Byte format
        abKey = _
        cnvBytesFromHexStr("2447EC44111548FBB670B98F182D5DEE109BF5F30D9464ED411F18A63C53A998")
        abBlock = cnvBytesFromHexStr("15173A0EB65F5CC05E704EFE61D9E346")
        abCorrect = cnvBytesFromHexStr("85F083ACC676D91EDD1ABFB43935237A")
        
        Debug.Print "AES Monte Carlo ECB Mode Decrypt:"
        Debug.Print "KY=" & cnvHexStrFromBytes(abKey)
        Debug.Print "CT=" & cnvHexStrFromBytes(abBlock)
        
        hContext = AES256_Init(abKey(0), DECRYPT, "ECB", 0)
        If hContext = 0 Then
            MsgBox "Failed to set context", vbCritical
            Exit Sub
        End If
        ' Do 10,000 times
        For j = 0 To 9999
            nRet = AES256_Update(hContext, abBlock(0), 16)
        Next
        Debug.Print "PT=" & cnvHexStrFromBytes(abBlock)
        Debug.Print "OK=" & cnvHexStrFromBytes(abCorrect)
        nRet = AES256_Final(hContext)
        
        Debug.Assert (StrConv(abCorrect, vbUnicode) = StrConv(abBlock, vbUnicode))

End Sub

Public Sub V_Test_AES256_UpdateHex()
    Debug.Print "Testing AES256_UpdateHex ..."
        Dim nRet As Long
        Dim hContext As Long
        Dim sBlock As String
        Dim strHexKey As String
        Dim strIV As String
        Dim sNext As String
        Dim sLast As String
        Dim sCorrect As String
        Dim j As Integer
      
    ' cbc_e_m.txt
    ' KEYSIZE=256 I=2
    ' KEY=33A36646FE56F70DC0C51A3117E639F182DEF8CAB5C06671EEA0407C48A9C757
    ' IV=7CE2ABAF8BEF23C4816DC8CE842048A7
    ' PT=81EA5BA46945C1705F6F89778868CC67
    ' CT=50CD14A12C6852D39654C816BFAF9AC2
        
        strHexKey = _
        "33A36646FE56F70DC0C51A3117E639F182DEF8CAB5C06671EEA0407C48A9C757"
        strIV = "7CE2ABAF8BEF23C4816DC8CE842048A7"
        sBlock = "81EA5BA46945C1705F6F89778868CC67"
        sCorrect = "50CD14A12C6852D39654C816BFAF9AC2"
        
        Debug.Print "AES Monte Carlo CBC Mode Encrypt:"
        Debug.Print "KY=" & strHexKey
        Debug.Print "IV=" & strIV
        Debug.Print "PT=" & sBlock
        
        hContext = AES256_InitHex(strHexKey, ENCRYPT, "CBC", strIV)
        If hContext = 0 Then
            MsgBox "Failed to set context", vbCritical
            Exit Sub
        End If
        ' Do 10,000 times
        sNext = sBlock
        For j = 0 To 9999
            sBlock = sNext
            nRet = AES256_UpdateHex(hContext, sBlock)
            If j = 0 Then
                sNext = strIV
            Else
                sNext = sLast
            End If
            sLast = sBlock
        Next
        Debug.Print "CT=" & sBlock
        Debug.Print "OK=" & sCorrect
        nRet = AES256_Final(hContext)
        
        Debug.Assert (sCorrect = sBlock)

End Sub

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

End Sub

Public Sub V_Test_API_ErrorCode()
    Debug.Print "Testing API_ErrorCode ..."
    Dim nErrCode As Long
    nErrCode = API_ErrorCode()

End Sub

Public Sub V_Test_API_ErrorLookup()
    Debug.Print "Testing API_ErrorLookup ..."
    Dim nErrCode As Long
    nErrCode = 33
    Debug.Print "ErrorLookup(" & nErrCode & ")=" & apiErrorLookup(nErrCode)

End Sub

Public Sub V_Test_API_ErrorLookup2()
    Debug.Print "Testing API_ErrorLookup ..."
        Dim nRet As Long
        Dim strErrMsg As String * 128
        Dim i As Integer
        
        For i = 0 To 10000
            nRet = API_ErrorLookup(strErrMsg, Len(strErrMsg), i)
            If (nRet > 0) Then
                Debug.Print i & " = " & Left(strErrMsg, nRet)
            End If
        Next

End Sub

Public Sub V_Test_API_LicenceType()
    Debug.Print "Testing API_LicenceType ..."
        Dim nRet As Long
        nRet = API_LicenceType(0)
        Debug.Print "API_LicenceType is " & Chr(nRet)

End Sub

Public Sub V_Test_API_PowerUpTests()
    Debug.Print "Testing API_PowerUpTests ..."
    Dim nRet As Long
    nRet = API_PowerUpTests(0)
    Debug.Print "API_PowerUpTests returns " & nRet

End Sub

Public Sub V_Test_API_Version()
    Debug.Print "Testing API_Version ..."
    Dim nRet As Long
    nRet = API_Version()
    Debug.Print "API_Version returns " & nRet

End Sub

Public Sub V_Test_BLF_B64Mode()
    Debug.Print "Testing BLF_B64Mode ..."
        Dim nRet As Long
        Dim strOutput As String
        Dim strInput As String
        Dim strKey As String
        Dim strIV As String
        Dim sCorrect As String
    
        ' "7654321 Now is the time for " padded to 32 bytes with 4 nulls
        strInput = "NzY1NDMyMSBOb3cgaXMgdGhlIHRpbWUgZm9yIAAAAAA="
        sCorrect = "a3e01jAG3uYFsVbidAOXk1jeuecVRhbZWfFlK9X/ksw="
        ' Key is 0x0123456789ABCDEFF0E1D2C3B4A59687
        strKey = "ASNFZ4mrze/w4dLDtKWWhw=="
        ' IV is 0xFEDCBA9876543210
        strIV = "/ty6mHZUMhA="
        ' Set strOutput to be same length as strInput
        strOutput = String(Len(strInput), " ")
    
        Debug.Print "KY=" & strKey
        Debug.Print "IV=" & strIV
        Debug.Print "PT=" & strInput
        ' Encrypt in one-off process
        nRet = BLF_B64Mode(strOutput, strInput, strKey, ENCRYPT, "CBC", strIV)
        Debug.Print "CT=" & strOutput, nRet
        Debug.Print "OK=" & sCorrect
    
        ' Now decrypt back to plain text
        strInput = strOutput
        nRet = BLF_B64Mode(strOutput, strInput, strKey, DECRYPT, "CBC", strIV)
        Debug.Print "P'=" & strOutput, nRet

End Sub

Public Sub V_Test_BLF_Bytes()
    Debug.Print "Testing BLF_Bytes ..."
    Dim nRet As Long
    Dim strInput As String
    Dim strKey As String
    Dim sCorrect As String
    Dim nKeyLen As Long
    Dim abKey() As Byte
    Dim abOutput() As Byte
    Dim abData() As Byte
    Dim nDataLen As Long
    
    ' Define test vectors in hex
    strKey = "FEDCBA9876543210"
    strInput = "0123456789ABCDEF0123456789ABCDEF"
    sCorrect = "0ACEAB0FC6A0A28D0ACEAB0FC6A0A28D"
    
    ' Convert to byte arrays and compute lengths
    nKeyLen = Len(strKey) \ 2
    abKey = cnvBytesFromHexStr(strKey)
    nDataLen = Len(strInput) \ 2
    abData = cnvBytesFromHexStr(strInput)
    
    ' Dimension array for output
    ReDim abOutput(nDataLen - 1)
    
    Debug.Print "KY=" & cnvHexStrFromBytes(abKey)
    Debug.Print "PT=" & cnvHexStrFromBytes(abData)
    ' Encrypt in one-off process
    nRet = BLF_Bytes(abOutput(0), abData(0), nDataLen, abKey(0), nKeyLen, ENCRYPT)
    Debug.Print "CT=" & cnvHexStrFromBytes(abOutput), nRet
    Debug.Print "OK=" & sCorrect
    
    ' Now decrypt back
    nRet = BLF_Bytes(abData(0), abOutput(0), nDataLen, abKey(0), nKeyLen, DECRYPT)
    Debug.Print "P'=" & cnvHexStrFromBytes(abData), nRet

End Sub

Public Sub V_Test_BLF_BytesMode()
    Debug.Print "Testing BLF_BytesMode ..."
        Dim nRet As Long
        Dim strOutput As String
        Dim strInput As String
        Dim strKey As String
        Dim strHexIV As String
        Dim sCorrect As String
        Dim nKeyLen As Long
        Dim abKey() As Byte
        Dim abOutput() As Byte
        Dim abData() As Byte
        Dim nDataLen As Long
        Dim abInitV() As Byte
        Dim nIvLen As Long
        
        strKey = "0123456789ABCDEFF0E1D2C3B4A59687"
        strHexIV = "FEDCBA9876543210"
        strInput = _
    "37363534333231204E6F77206973207468652074696D6520666F722000000000"
        sCorrect = _
    "6B77B4D63006DEE605B156E27403979358DEB9E7154616D959F1652BD5FF92CC"
        
        ' Convert to byte arrays and compute lengths
        nKeyLen = Len(strKey) \ 2
        nDataLen = Len(strInput) \ 2
        nIvLen = Len(strHexIV) \ 2
        abKey = cnvBytesFromHexStr(strKey)
        abData = cnvBytesFromHexStr(strInput)
        abInitV = cnvBytesFromHexStr(strHexIV)
        
        ' Dimension array for output
        ReDim abOutput(nDataLen - 1)
        
        Debug.Print "KY=" & cnvHexStrFromBytes(abKey)
        Debug.Print "IV=" & cnvHexStrFromBytes(abInitV)
        Debug.Print "PT=" & cnvHexStrFromBytes(abData)
        ' Encrypt in one-off process
        nRet = BLF_BytesMode(abOutput(0), abData(0), nDataLen, abKey(0), _
            nKeyLen, ENCRYPT, "CBC", abInitV(0))
        Debug.Print "CT=" & cnvHexStrFromBytes(abOutput), nRet
        Debug.Print "OK=" & sCorrect
        
        ' Now decrypt back
        nRet = BLF_BytesMode(abData(0), abOutput(0), nDataLen, abKey(0), _
            nKeyLen, DECRYPT, "cbc", abInitV(0))
        Debug.Print "P'=" & cnvHexStrFromBytes(abData), nRet

End Sub

Public Sub V_Test_BLF_File()
    Debug.Print "Testing BLF_File ..."
        Const MY_PATH As String = ""
        Dim abKey() As Byte
        Dim strFileOut As String
        Dim strFileIn As String
        Dim strFileChk As String
        Dim nRet As Long
        Dim nBytes As Long
    
        ' Construct full path names to files
        strFileIn = MY_PATH & "hello.txt"
        strFileOut = MY_PATH & "hello.blf.enc.dat"
        strFileChk = MY_PATH & "hello.blf.chk.txt"
    
        ' Create the key as an array of bytes
        ' This creates an array of 8 bytes {&HFE, &HDC, ... &H10}
        abKey = cnvBytesFromHexStr("fedcba9876543210")
        nBytes = 8
    
        ' Encrypt plaintext file to cipher
        ' WARNING: output file is just clobbered
        nRet = BLF_File(strFileOut, strFileIn, abKey(0), nBytes, ENCRYPT, "ECB", 0)
        Debug.Print nRet
        ' Output file should be a 16-byte file hello.enc
        ' containing the following values in hexadecimal:
        ' 1A A1 51 B7 7A 5A 33 5C 4E 7E DC 84 A3 86 DC 96
    
        ' Now decrypt it
        nRet = BLF_File(strFileChk, strFileOut, abKey(0), nBytes, DECRYPT, "ECB", 0)
        Debug.Print nRet

End Sub

Public Sub V_Test_BLF_FileExt()
    Debug.Print "Testing BLF_FileExt ..."
    
End Sub

Public Sub V_Test_BLF_FileHex()
    Debug.Print "Testing BLF_FileHex ..."
        Dim nRet As Long
    
        ' Encrypt plaintext file to cipher
        nRet = BLF_FileHex("bigfile.cbc", "bigfile.dat", _
            "fedcba9876543210fedcba9876543210", ENCRYPT, "CBC", "0123456789abcdef")
        Debug.Print nRet

End Sub

Public Sub V_Test_BLF_Hex()
    Debug.Print "Testing BLF_Hex ..."
        Dim nRet As Long
        Dim strOutput As String
        Dim strInput As String
        Dim strKey As String
        Dim sCorrect As String
    
        strInput = "0123456789ABCDEF"
        strKey = "FEDCBA9876543210"
        sCorrect = "0ACEAB0FC6A0A28D"
        ' Set strOutput to be same length as strInput
        strOutput = String(Len(strInput), " ")
    
        Debug.Print "KY=" & strKey
        Debug.Print "PT=" & strInput
        ' Encrypt in one-off process
        nRet = BLF_Hex(strOutput, strInput, strKey, ENCRYPT)
        Debug.Print "CT=" & strOutput
        Debug.Print "OK=" & sCorrect
    
        ' Now decrypt back to plain text
        strInput = strOutput
        nRet = BLF_Hex(strOutput, strInput, strKey, DECRYPT)
        Debug.Print "P'=" & strOutput

End Sub

Public Sub V_Test_BLF_HexMode()
    Debug.Print "Testing BLF_HexMode ..."
        Dim nRet As Long
        Dim strOutput As String
        Dim strInput As String
        Dim strHexKey As String
        Dim strHexIV As String
        Dim sCorrect As String
    
        ' "7654321 Now is the time for " padded to 32 bytes with 4 nulls
        strInput = "37363534333231204E6F77206973207468652074696D6520666F722000000000"
        sCorrect = "6B77B4D63006DEE605B156E27403979358DEB9E7154616D959F1652BD5FF92CC"
        strHexKey = "0123456789ABCDEFF0E1D2C3B4A59687"
        strHexIV = "FEDCBA9876543210"
        ' Set strOutput to be same length as strInput
        strOutput = String(Len(strInput), " ")
    
        Debug.Print "KY=" & strHexKey
        Debug.Print "IV=" & strHexIV
        Debug.Print "PT=" & strInput
        ' Encrypt in one-off process
        nRet = BLF_HexMode(strOutput, strInput, strHexKey, ENCRYPT, "CBC", strHexIV)
        Debug.Print "CT=" & strOutput, nRet
        Debug.Print "OK=" & sCorrect
    
        ' Now decrypt back to plain text
        strInput = strOutput
        nRet = BLF_HexMode(strOutput, strInput, strHexKey, DECRYPT, "CBC", strHexIV)
        Debug.Print "P'=" & strOutput, nRet

End Sub

Public Sub V_Test_BLF_Update()
    Debug.Print "Testing BLF_Update ..."
        ' Contrived example to encrypt sample blocks in CBC mode
        Dim abBlock(7) As Byte
        Dim abKey() As Byte
        Dim nKeyLen As Long
        Dim abInitV() As Byte
        Dim hContext As Long
        Dim nRet As Long
        Dim i As Integer
        Dim j As Integer
       
        ' Specify a key and its length
        abKey = cnvBytesFromHexStr("FEDCBA9876543210")
        nKeyLen = UBound(abKey) - LBound(abKey) + 1
        
        ' And an IV (length is assumed to be 8 bytes)
        abInitV = cnvBytesFromHexStr("0123456789abcdef")
        
        ' Initialise the context
        hContext = BLF_Init(abKey(0), nKeyLen, ENCRYPT, "CBC", abInitV(0))
        If hContext = 0 Then
            nRet = BLF_InitError()
            Debug.Print "BFL_Init Failed: " & apiErrorLookup(nRet)
            Exit Sub
        End If
        
        Debug.Print "KY=" & cnvHexStrFromBytes(abKey)
        Debug.Print "IV=" & cnvHexStrFromBytes(abInitV)
        
        ' Create some test blocks and encrypt them
        For i = 1 To 4
            For j = 0 To 7
                abBlock(j) = CByte(i)
            Next
            Debug.Print "PT(" & i & ")=" & cnvHexStrFromBytes(abBlock)
            nRet = BLF_Update(hContext, abBlock(0), 8)
            Debug.Print "CT(" & i & ")=" & cnvHexStrFromBytes(abBlock)
        Next
        
        ' Clear the context
        BLF_Final (hContext)

End Sub

Public Sub V_Test_BLF_UpdateHex()
    Debug.Print "Testing BLF_UpdateHex ..."
        Dim nRet As Long
        Dim hContext As Long
        Dim strKey As String
        Dim strHexString As String
        Dim sCorrect As String
    
        strKey = "0123456789abcdef"
        Debug.Print "KY=" & strKey
    
        ' Initialise the context
        hContext = BLF_InitHex(strKey, True, "ECB", "")
        If hContext = 0 Then
            ' Always check for error
            MsgBox "Unable to initialise BLF context", vbCritical
            Exit Sub
        End If
    
        '              "Now is t"
        strHexString = "4e6f772069732074"
        Debug.Print "PT=" & strHexString
        nRet = BLF_UpdateHex(hContext, strHexString)
        Debug.Print "CT=" & strHexString
        Debug.Print "OK=" & "cb08e682c67e32e2"
    
        '              "he time for all"
        strHexString = "68652074696d6520666f7220616c6c20"
        Debug.Print "PT=" & strHexString
        nRet = BLF_UpdateHex(hContext, strHexString)
        Debug.Print "CT=" & strHexString
        Debug.Print "OK=" & "8fcb010ac2ce9b1d9c4538762e33b52f"
    
        nRet = BLF_Final(hContext)

End Sub

Public Sub V_Test_CIPHER_DecryptBytes2()
    Debug.Print "Testing CIPHER_DecryptBytes2 ..."
    Dim key() As Byte
    Dim iv() As Byte
    Dim pn() As Byte
    Dim ct() As Byte
    Dim ok() As Byte
    Dim p1() As Byte
    Dim pnlen As Long
    Dim ctlen As Long
    Dim p1len 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))
    ct = cnvBytesFromHexStr("C3153108A8DD340C0BCB1DFE8D25D2320EE0E66BD2BB4A313FB75C5638E9E1771D4CDA34FBFB7E74B321F9A2CF4EA61B")
    ctlen = UBound(ct) + 1
    ' OK = "Now is the time for all good men to"
    ok = cnvBytesFromHexStr("4E6F77206973207468652074696D6520666F7220616C6C20676F6F64206D656E20746F")
    
    ' DECRYPT
    ' 1. Output from decryption is always <= length of input so allocate it first
    p1len = ctlen
    ReDim p1(p1len - 1)
    ' 2. Perform decryption including padding into output buffer
    p1len = CIPHER_DecryptBytes2(p1(0), p1len, ct(0), ctlen, key(0), keylen, iv(0), ivlen, algstr, 0)
    Debug.Print "CIPHER_DecryptBytes2 returns " & p1len
    ' 3. Re-dimension the output to the correct length
    ReDim Preserve p1(p1len - 1)
    
    Debug.Print ("P1=" & cnvHexStrFromBytes(p1))
    Debug.Print ("P1='" & StrConv(p1, vbUnicode) + "'")
    
    Debug.Print "Check actual padding by decrypting with NoPadding..."
    algstr = "Aes128/CBC/NoPadding"
    Debug.Print algstr
    ReDim pn(ctlen - 1)
    pnlen = CIPHER_DecryptBytes2(pn(0), pnlen, ct(0), ctlen, key(0), keylen, iv(0), ivlen, algstr, 0)
    Debug.Print "CIPHER_DecryptBytes2(NoPadding) returns " & pnlen
    Debug.Print ("Pn=" & cnvHexStrFromBytes(pn))

End Sub

Public Sub V_Test_CIPHER_EncryptBytes2()
    Debug.Print "Testing CIPHER_EncryptBytes2 ..."
    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_EncryptBytes2(0, 0, pt(0), ptlen, key(0), keylen, iv(0), ivlen, algstr, 0)
    Debug.Print "CIPHER_EncryptBytes2 returns " & ctlen
    ' 2. Allocate the buffer
    ReDim ct(ctlen - 1)
    ' 3. Encrypt to output buffer
    ctlen = CIPHER_EncryptBytes2(ct(0), ctlen, pt(0), ptlen, key(0), keylen, iv(0), ivlen, algstr, 0)
    
    Debug.Print ("CT=" & cnvHexStrFromBytes(ct))
    Debug.Print ("OK=" & cnvHexStrFromBytes(ok))

End Sub

Public Sub V_Test_CIPHER_FileEncrypt()
    Debug.Print "Testing CIPHER_FileEncrypt ..."
    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(API_BLK_AES_BYTES - 1)
    Call RNG_NonceData(abIV(0), API_BLK_AES_BYTES)
    ' 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, API_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, API_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_KeyWrap()
    Debug.Print "Testing CIPHER_KeyWrap ..."
    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
    
    Debug.Print "INPUT:"
    Debug.Print "KEK=" & cnvHexStrFromBytes(abKek)
    Debug.Print "KD =" & cnvHexStrFromBytes(abKeyData)
    Debug.Print "OUTPUT:"
    
    nWkLen = CIPHER_KeyWrap(0, 0, abKeyData(0), nKdLen, abKek(0), nKekLen, API_BC_AES128)
    If nWkLen <= 0 Then
        Debug.Print "CIPHER_KeyWrap returns " & nWkLen & ": " & apiErrorLookup(nWkLen)
        Exit Sub
    End If
    ReDim abWK(nWkLen - 1)
    nWkLen = CIPHER_KeyWrap(abWK(0), nWkLen, abKeyData(0), nKdLen, abKek(0), nKekLen, API_BC_AES128)
    Debug.Print "WK{AES-128}=" & 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, API_BC_AES256)
    If nWkLen <= 0 Then
        Debug.Print "CIPHER_KeyWrap returns " & nWkLen & ": " & apiErrorLookup(nWkLen)
        Exit Sub
    End If
    ReDim abWK(nWkLen - 1)
    nWkLen = CIPHER_KeyWrap(abWK(0), nWkLen, abKeyData(0), nKdLen, abKek(0), nKekLen, API_BC_AES256)
    Debug.Print "WK{AES-256}=" & 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
    
    Debug.Print "INPUT:"
    Debug.Print "KEK=" & cnvHexStrFromBytes(abKek)
    Debug.Print "KD =" & cnvHexStrFromBytes(abKeyData)
    Debug.Print "OUTPUT:"
    
    nWkLen = CIPHER_KeyWrap(0, 0, abKeyData(0), nKdLen, abKek(0), nKekLen, API_BC_3DES)
    If nWkLen <= 0 Then
        Debug.Print "CIPHER_KeyWrap returns " & nWkLen & ": " & apiErrorLookup(nWkLen)
        Exit Sub
    End If
    ReDim abWK(nWkLen - 1)
    nWkLen = CIPHER_KeyWrap(abWK(0), nWkLen, abKeyData(0), nKdLen, abKek(0), nKekLen, API_BC_3DES)
    Debug.Print "WK(3DES}=" & cnvHexStrFromBytes(abWK)
    
    ' Now unwrap (decrypt)...
    Debug.Print "Unwrap..."
    Debug.Print "INPUT:"
    Debug.Print "ALG=3DES"
    Debug.Print "KEK=" & cnvHexStrFromBytes(abKek)
    Debug.Print "WK =" & cnvHexStrFromBytes(abWK)
    ' In this case, we know that the Triple DES key will be exactly 24 bytes long, so
    nKdLen = API_KEYSIZE_TDEA_BYTES
    ReDim abKeyData(nKdLen - 1)
    nKdLen = CIPHER_KeyUnwrap(abKeyData(0), nKdLen, abWK(0), nWkLen, abKek(0), nKekLen, API_BC_3DES)
    If nKdLen <= 0 Then
        Debug.Print "CIPHER_KeyUnwrap returns " & nKdLen & ": " & apiErrorLookup(nKdLen)
        Exit Sub
    End If
    Debug.Print "OUTPUT:"
    Debug.Print "KD =" & cnvHexStrFromBytes(abKeyData)
    Debug.Print "OK =84E7F2D878F89FCCCD2D5EBAFC56DAF73300F27EF771CD68"

End Sub

Public Sub V_Test_CIPHER_KeyUnwrap()
    Debug.Print "Testing CIPHER_KeyUnwrap ..."
    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
    Debug.Print "INPUT:"
    Debug.Print "KEK=" & cnvHexStrFromBytes(abKek)
    Debug.Print "WK =" & cnvHexStrFromBytes(abWK)
    Debug.Print "ALG=AES-128"
       
    nKdLen = CIPHER_KeyUnwrap(0, 0, abWK(0), nWkLen, abKek(0), nKekLen, API_BC_AES128)
    If nKdLen <= 0 Then
        Debug.Print "CIPHER_KeyUnwrap returns " & nKdLen & ": " & apiErrorLookup(nKdLen)
        Exit Sub
    End If
    ReDim abKeyData(nKdLen - 1)
    nKdLen = CIPHER_KeyUnwrap(abKeyData(0), nKdLen, abWK(0), nWkLen, abKek(0), nKekLen, API_BC_AES128)
    Debug.Print "OUTPUT:"
    Debug.Print "KD =" & cnvHexStrFromBytes(abKeyData)
    Debug.Print "OK =00112233445566778899AABBCCDDEEFF"

End Sub

Public Sub V_Test_CIPHER_StreamBytes()
    Debug.Print "Testing CIPHER_StreamBytes ..."
    Dim abKey() As Byte
    Dim abInput() As Byte
    Dim abOutput() As Byte
    Dim nRet As Long
    Dim nDataLen As Long
    Dim nKeyLen As Long
    Dim strCorrect As String
    
    ' Arcfour test vector
    abKey = cnvBytesFromHexStr("0123456789abcdef")
    abInput = cnvBytesFromHexStr("0123456789abcdef")
    strCorrect = "75b7878099e0c596"
    
    ReDim abOutput(UBound(abInput))
    nDataLen = UBound(abInput) + 1
    nKeyLen = UBound(abKey) + 1
    
    Debug.Print "KY=" & cnvHexStrFromBytes(abKey)
    Debug.Print "PT=" & cnvHexStrFromBytes(abInput)
    ' Encipher using Arcfour
    nRet = CIPHER_StreamBytes(abOutput(0), abInput(0), nDataLen, abKey(0), nKeyLen, vbNull, 0, 0, API_SC_ARCFOUR)
    Debug.Print "CT=" & cnvHexStrFromBytes(abOutput)
    Debug.Print "OK=" & strCorrect
    
    ' Now decipher just by calling again. Use same output as input.
    nRet = CIPHER_StreamBytes(abOutput(0), abOutput(0), nDataLen, abKey(0), nKeyLen, vbNull, 0, 0, API_SC_ARCFOUR)
    Debug.Print "P'=" & cnvHexStrFromBytes(abOutput)

End Sub

Public Sub V_Test_CIPHER_StreamBytes2()
    Debug.Print "Testing CIPHER_StreamBytes ..."
    ' ChaCha20 test vector from "ChaCha20 and Poly1305 for IETF protocols"
    Dim abKey() As Byte
    Dim abInput() As Byte
    Dim abOutput() As Byte
    Dim abIV() As Byte
    Dim nRet As Long
    Dim nDataLen As Long
    Dim nKeyLen As Long
    Dim nIvLen As Long
    Dim strCorrect As String
    Dim strData As String
    
    ' Obtain parameters in byte array format
    abKey = cnvBytesFromHexStr("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f")
    abIV = cnvBytesFromHexStr("000000000000004a00000000")
    strData = _
    "Ladies and Gentlemen of the class of '99: If I could offer you only one tip for the future, sunscreen would be it."
    abInput = StrConv(strData, vbFromUnicode)
    strCorrect = _
    "6E2E359A2568F98041BA0728DD0D6981E97E7AEC1D4360C20A27AFCCFD9FAE0BF91B65C5524733AB8F593DABCD62B3571639D624E65152AB8F530C359F0861D807CA0DBF500D6A6156A38E088A22B65E52BC514D16CCF806818CE91AB77937365AF90BBF74A35BE6B40B8EEDF2785E42874D"
    
    ReDim abOutput(UBound(abInput))
    nDataLen = UBound(abInput) + 1
    nKeyLen = UBound(abKey) + 1
    nIvLen = UBound(abIV) + 1
    
    Debug.Print "KY=" & cnvHexStrFromBytes(abKey)
    Debug.Print "IV=" & cnvHexStrFromBytes(abIV)
    Debug.Print "PT=" & cnvHexStrFromBytes(abInput)
    ' Encipher using ChaCha20 with counter=1
    nRet = CIPHER_StreamBytes(abOutput(0), abInput(0), nDataLen, abKey(0), nKeyLen, abIV(0), nIvLen, 1, API_SC_CHACHA20)
    Debug.Print "CIPHER_StreamBytes returns " & nRet & " (expecting 0)"
    Debug.Print "CT=" & cnvHexStrFromBytes(abOutput)
    Debug.Print "OK=" & strCorrect
    
    ' Now decipher just by calling again. Use same output as input.
    nRet = CIPHER_StreamBytes(abOutput(0), abOutput(0), nDataLen, abKey(0), nKeyLen, abIV(0), nIvLen, 1, API_SC_CHACHA20)
    Debug.Print "P'=" & cnvHexStrFromBytes(abOutput)
    Debug.Print "P'=" & StrConv(abOutput, vbUnicode)

End Sub

Public Sub V_Test_CIPHER_StreamFile()
    Debug.Print "Testing CIPHER_StreamFile ..."
    Dim nRet As Long
    Dim strFileIn As String
    Dim strFileOut As String
    Dim abKey() As Byte
    Dim abInput() As Byte
    Dim abIV() As Byte
    Dim nKeyLen As Long
    Dim nIvLen As Long
    Dim nCounter As Long
    
    ' Obtain parameters in byte array format
    abKey = cnvBytesFromHexStr("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f")
    abIV = cnvBytesFromHexStr("000000000000004a00000000")
    nCounter = 1
    nKeyLen = UBound(abKey) + 1
    nIvLen = UBound(abIV) + 1
    Debug.Print "Key: " & cnvHexStrFromBytes(abKey)
    Debug.Print "IV:  " & cnvHexStrFromBytes(abIV)
    Debug.Print "Counter: " & nCounter
    
    ' Encipher plaintext file
    strFileIn = "sunscreen.txt"
    strFileOut = "sunscreen-chacha.dat"
    nRet = CIPHER_StreamFile(strFileOut, strFileIn, abKey(0), nKeyLen, abIV(0), nIvLen, nCounter, API_SC_CHACHA20)
    Debug.Print "CIPHER_StreamFile returns " & nRet & " (expecting 0)"

End Sub

Public Sub V_Test_CIPHER_StreamHex()
    Debug.Print "Testing CIPHER_StreamHex ..."
    ' Ref: eSTREAM `verified.test-vectors.txt` Set 3, vector#  0:
    Dim nRet As Long
    Dim strKey As String
    Dim strIV As String
    Dim strInput As String
    Dim strOutput As String
    Dim strCorrect As String
    Dim strCheck As String
    
    ' Parameters are hex-encoded strings
    strKey = "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F"
    strIV = "0000000000000000"
    ' Key stream is generated by encrypting 32 zero bytes (=64 hex chars)
    strInput = "0000000000000000000000000000000000000000000000000000000000000000"
    strCorrect = "B580F7671C76E5F7441AF87C146D6B513910DC8B4146EF1B3211CF12AF4A4B49"
    Debug.Print "KY=" & strKey
    Debug.Print "IV=" & strIV
    Debug.Print "PT=" & strInput
    ' Encipher using Salsa20 in hex mode
    strOutput = String(Len(strInput), " ")
    nRet = CIPHER_StreamHex(strOutput, Len(strOutput), strInput, strKey, strIV, 0, API_SC_SALSA20)
    Debug.Print "CT=" & strOutput
    Debug.Print "OK=" & strCorrect

End Sub

Public Sub V_Test_CIPHER_StreamInit()
    Debug.Print "Testing CIPHER_StreamInit ..."
    ' Ref: `draft-strombergson-chacha-test-vectors-02.txt` TC7: Sequence patterns in key and IV. Rounds: 20
    Dim nRet As Long
    Dim strFileIn As String
    Dim strFileOut As String
    Dim abKey() As Byte
    Dim abIV() As Byte
    Dim abInput() As Byte
    Dim abOutput() As Byte
    Dim nKeyLen As Long
    Dim nIvLen As Long
    Dim strCorrect As String
    Dim nDataLen As Long
    Dim hContext As Long
    
    ' Use incremental functions to encrypt a 65-byte input of zeros in chunks of 1, 62 and 2 bytes
    Debug.Print "CHACHA20 (INCREMENTAL):"
    strCorrect = "9fadf409c00811d00431d67efbd88fba59218d5d6708b1d685863fabbb0e961eea480fd6fb532bfd494b2151015057423ab60a63fe4f55f7a212e2167ccab931fb"
    ' Obtain parameters in byte array format
    abKey = cnvBytesFromHexStr("00112233445566778899aabbccddeeffffeeddccbbaa99887766554433221100")
    abIV = cnvBytesFromHexStr("0f1e2d3c4b5a6978")
    nKeyLen = UBound(abKey) + 1
    nIvLen = UBound(abIV) + 1
    Debug.Print "Key: " & cnvHexStrFromBytes(abKey)
    Debug.Print "IV:  " & cnvHexStrFromBytes(abIV)
    
    ' Initialize CIPHERSTREAM context
    hContext = CIPHER_StreamInit(abKey(0), nKeyLen, abIV(0), nIvLen, 0, API_SC_CHACHA20)
    If (hContext = 0) Then
        Debug.Print "ERROR: " + API_ErrorCode()
        Exit Sub
    End If
    
    ' Part 1: block of 1 byte
    nDataLen = 1
    ReDim abInput(nDataLen - 1)   ' Set to zero by default
    ReDim abOutput(UBound(abInput))
    nRet = CIPHER_StreamUpdate(hContext, abOutput(0), abInput(0), nDataLen)
    Debug.Print cnvHexStrFromBytes(abOutput)
    
    ' Part 2: block of 62 bytes
    nDataLen = 62
    ReDim abInput(nDataLen - 1)
    ReDim abOutput(UBound(abInput))
    nRet = CIPHER_StreamUpdate(hContext, abOutput(0), abInput(0), nDataLen)
    Debug.Print cnvHexStrFromBytes(abOutput)
    
    ' Part 3: block of 2 bytes
    nDataLen = 2
    ReDim abInput(nDataLen - 1)
    ReDim abOutput(UBound(abInput))
    nRet = CIPHER_StreamUpdate(hContext, abOutput(0), abInput(0), nDataLen)
    Debug.Print cnvHexStrFromBytes(abOutput)
    
    Debug.Print "CORRECT="
    Debug.Print strCorrect
    
    ' We are done with context
    nRet = CIPHER_StreamFinal(hContext)
    Debug.Print "CIPHER_StreamFinal retrurns " & nRet & " (expecting 0)"

End Sub

Public Sub V_Test_CRC_Bytes()
    Debug.Print "Testing CRC_Bytes ..."
    Dim abData() As Byte
    Dim nLen As Long
    Dim nCRC As Long
    Dim i As Long
    
    nLen = 9
    ReDim abData(nLen - 1)
    ' Create a 9-byte array equal to "123456789"
    For i = 0 To nLen - 1
        abData(i) = i + Asc("1")
    Next
    nCRC = CRC_Bytes(abData(0), nLen, 0)
    Debug.Print "CRC32=" & Hex(nCRC)

End Sub

Public Sub V_Test_CRC_File()
    Debug.Print "Testing CRC_File ..."
    Dim nCRC As Long
    nCRC = CRC_File("hello.txt", 0)
    Debug.Print "CRC32('hello.txt')=" & Hex(nCRC)

End Sub

Public Sub V_Test_CRC_String()
    Debug.Print "Testing CRC_String ..."
    Dim strData As String
    Dim nCRC As Long
    
    strData = "123456789"
    nCRC = CRC_String(strData, 0)
    Debug.Print "CRC32(" & strData & ")=" & Hex(nCRC)

End Sub

Public Sub V_Test_DES_B64Mode()
    Debug.Print "Testing DES_B64Mode ..."
    Dim nRet As Long
    Dim strOutput As String
    Dim strInput As String
    Dim strKey As String
    Dim strIV As String
    Dim sCorrect As String
    
    ' Key:        "0123456789abcdef"
    ' IV:         "1234567890abcdef"
    ' Plaintext:  "Now is the time for all "
    '             "4e6f77206973207468652074696d6520666f7220616c6c20"
    ' Ciphertext: "e5c7cdde872bf27c43e934008c389c0f683788499a7c05f6"
    strInput = "Tm93IGlzIHRoZSB0aW1lIGZvciBhbGwg"
    strKey = "ASNFZ4mrze8="
    strIV = "EjRWeJCrze8="
    sCorrect = "5cfN3ocr8nxD6TQAjDicD2g3iEmafAX2"
    
    ' Set strOutput to be same length as strInput
    strOutput = String(Len(strInput), " ")
    
    Debug.Print "KY=" & strKey
    Debug.Print "IV=" & strIV
    Debug.Print "PT=" & strInput
    ' Encrypt in one-off process
    nRet = DES_B64Mode(strOutput, strInput, strKey, True, "CBC", strIV)
    Debug.Print "CT=" & strOutput
    Debug.Print "OK=" & sCorrect
    
    ' Now decrypt back to plain text
    strInput = strOutput
    nRet = DES_B64Mode(strOutput, strInput, strKey, DECRYPT, "CBC", strIV)
    Debug.Print "P'=" & strOutput

End Sub

Public Sub V_Test_DES_Bytes()
    Debug.Print "Testing DES_Bytes ..."
        Dim nRet As Long
        Dim strInput As String
        Dim strKey As String
        Dim sCorrect As String
        Dim nKeyLen As Long
        Dim abKey() As Byte
        Dim abOutput() As Byte
        Dim abData() As Byte
        Dim nDataLen As Long
        
        ' Define test vectors in hex
        strKey = "0123456789abcdef"
        strInput = "4e6f77206973207468652074696d6520666f7220616c6c20"
        sCorrect = "3FA40E8A984D48156A271787AB8883F9893D51EC4B563B53"
        
        ' Convert to byte arrays and compute lengths
        nKeyLen = Len(strKey) \ 2
        abKey = cnvBytesFromHexStr(strKey)
        nDataLen = Len(strInput) \ 2
        abData = cnvBytesFromHexStr(strInput)
        
        ' Dimension array for output
        ReDim abOutput(nDataLen - 1)
        
        Debug.Print "KY=" & cnvHexStrFromBytes(abKey)
        Debug.Print "PT=" & cnvHexStrFromBytes(abData)
        ' Encrypt in one-off process
        nRet = DES_Bytes(abOutput(0), abData(0), nDataLen, abKey(0), ENCRYPT)
        Debug.Print "CT=" & cnvHexStrFromBytes(abOutput), nRet
        Debug.Print "OK=" & sCorrect
        Debug.Assert (sCorrect = cnvHexStrFromBytes(abOutput))
        
        ' Now decrypt back
        nRet = DES_Bytes(abData(0), abOutput(0), nDataLen, abKey(0), DECRYPT)
        Debug.Print "P'=" & cnvHexStrFromBytes(abData), nRet
        Debug.Assert (strInput = cnvHexStrFromBytes(abData))

End Sub

Public Sub V_Test_DES_BytesMode()
    Debug.Print "Testing DES_BytesMode ..."
        Dim nRet As Long
        Dim strOutput As String
        Dim strInput As String
        Dim strKey As String
        Dim strHexIV As String
        Dim sCorrect As String
        Dim nDataLen As Long
        Dim abKey() As Byte
        Dim abOutput() As Byte
        Dim abData() As Byte
        Dim abInitV() As Byte
        
        strKey = "0123456789abcdef"
        strHexIV = "1234567890abcdef"
        strInput = "Now is the time for all "
        sCorrect = "e5c7cdde872bf27c43e934008c389c0f683788499a7c05f6"
        
        ' Convert to byte arrays and compute lengths
        abKey = cnvBytesFromHexStr(strKey)
        abInitV = cnvBytesFromHexStr(strHexIV)
        abData = StrConv(strInput, vbFromUnicode)
        nDataLen = Len(strInput)
        
        ' Dimension array for output
        ReDim abOutput(nDataLen - 1)
        
        Debug.Print "KY=" & cnvHexStrFromBytes(abKey)
        Debug.Print "IV=" & cnvHexStrFromBytes(abInitV)
        Debug.Print "PT=" & cnvHexStrFromBytes(abData)
        
        ' Encrypt in one-off process
        nRet = DES_BytesMode(abOutput(0), abData(0), nDataLen, _
            abKey(0), True, "CBC", abInitV(0))
        Debug.Print "CT=" & cnvHexStrFromBytes(abOutput), nRet
        Debug.Print "OK=" & sCorrect
        Debug.Assert (sCorrect = cnvHexStrFromBytes(abOutput))
        
        ' Now decrypt back
        nRet = DES_BytesMode(abData(0), abOutput(0), nDataLen, _
            abKey(0), DECRYPT, "CBC", abInitV(0))
        strOutput = StrConv(abData(), vbUnicode)
        Debug.Print "P'=" & "[" & strOutput & "]"
        Debug.Assert (strOutput = strInput)

End Sub

Public Sub V_Test_DES_CheckKey()
    Debug.Print "Testing DES_CheckKey ..."
        Dim abKey() As Byte
        Dim nKeyBytes As Long
        Dim nRet As Long
        
        nKeyBytes = 8
        ReDim abKey(nKeyBytes - 1)
        ' Generate a random DES key
        nRet = RNG_KeyBytes(abKey(0), nKeyBytes, "", 0)
        Debug.Print cnvHexStrFromBytes(abKey)
        ' Check if it's OK
        nRet = DES_CheckKey(abKey(0), nKeyBytes)
        Debug.Print "DES_CheckKey returns " & nRet & " (" & apiErrorLookup(nRet) & ")"
        If nRet <> 0 Then
            ' Error...
        End If

End Sub

Public Sub V_Test_DES_CheckKeyHex()
    Debug.Print "Testing DES_CheckKeyHex ..."
        Dim nRet As Long
        Dim strKeyHex As String
        
        ' Weak key
        strKeyHex = "0101010101010101"
        nRet = DES_CheckKeyHex(strKeyHex)
        Debug.Print strKeyHex & " is " & IIf(nRet = 0, "OK", "BAD") & " (" & apiErrorLookup(nRet) & ")"
    
        ' Valid key by one bit
        strKeyHex = "0101010101010102"
        nRet = DES_CheckKeyHex(strKeyHex)
        Debug.Print strKeyHex & " is " & IIf(nRet = 0, "OK", "BAD") & " (" & apiErrorLookup(nRet) & ")"
    
        ' Another weak key
        strKeyHex = "01fe01fe01fe01fe"
        nRet = DES_CheckKeyHex(strKeyHex)
        Debug.Print strKeyHex & " is " & IIf(nRet = 0, "OK", "BAD") & " (" & apiErrorLookup(nRet) & ")"
    
        ' Weak double key in 1st half
        strKeyHex = "01010101010101010001112223334455"
        nRet = DES_CheckKeyHex(strKeyHex)
        Debug.Print strKeyHex & " is " & IIf(nRet = 0, "OK", "BAD") & " (" & apiErrorLookup(nRet) & ")"
    
        ' Weak triple key in 3rd part
        strKeyHex = "000111222333444555666777888999aa0101010101010101"
        nRet = DES_CheckKeyHex(strKeyHex)
        Debug.Print strKeyHex & " is " & IIf(nRet = 0, "OK", "BAD") & " (" & apiErrorLookup(nRet) & ")"
    
        ' Valid key
        strKeyHex = "000111222333444555666777888999aaabbbcccdddeeefff"
        nRet = DES_CheckKeyHex(strKeyHex)
        Debug.Print strKeyHex & " is " & IIf(nRet = 0, "OK", "BAD") & " (" & apiErrorLookup(nRet) & ")"
    
        ' Wrong key length (missing 'f' at end)
        strKeyHex = "000111222333444555666777888999aaabbbcccdddeeeff"
        nRet = DES_CheckKeyHex(strKeyHex)
        Debug.Print strKeyHex & " is " & IIf(nRet = 0, "OK", "BAD") & " (" & apiErrorLookup(nRet) & ")"

End Sub

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

End Sub

Public Sub V_Test_DES_FileExt()
    Debug.Print "Testing DES_FileExt ..."
    
End Sub

Public Sub V_Test_DES_FileHex()
    Debug.Print "Testing DES_FileHex ..."
        Dim nRet As Long
    
        nRet = DES_FileHex("bigfile.cbc", "bigfile.dat", _
            "fedcba9876543210", ENCRYPT, "CBC", "0123456789abcdef")
        Debug.Print nRet
    
        ' and decrypt it as a check
        nRet = DES_FileHex("bigfile.chk", "bigfile.cbc", _
            "fedcba9876543210fedcba9876543210", DECRYPT, "CBC", "0123456789abcdef")
        Debug.Print nRet

End Sub

Public Sub V_Test_DES_Hex()
    Debug.Print "Testing DES_Hex ..."
        Dim nRet As Long
        Dim strOutput As String
        Dim strInput As String
        Dim strKey As String
        Dim sCorrect As String
    
        ' "Now is t" in hex
        strInput = "4e6f772069732074"
        strKey = "0123456789abcdef"
        sCorrect = "3fa40e8a984d4815"
        ' Set strOutput to be same length as strInput
        strOutput = String(Len(strInput), " ")
    
        Debug.Print "KY=" & strKey
        Debug.Print "PT=" & strInput
        ' Encrypt in one-off process
        nRet = DES_Hex(strOutput, strInput, strKey, ENCRYPT)
        Debug.Print "CT=" & strOutput
        Debug.Print "OK=" & sCorrect
    
        ' Now decrypt back to plain text
        strInput = strOutput
        nRet = DES_Hex(strOutput, strInput, strKey, DECRYPT)
        Debug.Print "P'=" & strOutput

End Sub

Public Sub V_Test_DES_HexMode()
    Debug.Print "Testing DES_HexMode ..."
        Dim nRet As Long
        Dim strOutput As String
        Dim strInput As String
        Dim strKey As String
        Dim strIV As String
        Dim sCorrect As String
    
        ' "Now is the time for all " in hex
        strInput = "4e6f77206973207468652074696d6520666f7220616c6c20"
        strKey = "0123456789abcdef"
        strIV = "1234567890abcdef"
        sCorrect = "e5c7cdde872bf27c43e934008c389c0f683788499a7c05f6"
        ' Set strOutput to be same length as strInput
        strOutput = String(Len(strInput), " ")
    
        Debug.Print "KY=" & strKey
        Debug.Print "IV=" & strIV
        Debug.Print "PT=" & strInput
        ' Encrypt in one-off process
        nRet = DES_HexMode(strOutput, strInput, strKey, True, "CBC", strIV)
        Debug.Print "CT=" & strOutput
        Debug.Print "OK=" & sCorrect
    
        ' Now decrypt back to plain text
        strInput = strOutput
        nRet = DES_HexMode(strOutput, strInput, strKey, DECRYPT, "CBC", strIV)
        Debug.Print "P'=" & strOutput

End Sub

Public Sub V_Test_DES_Update()
    Debug.Print "Testing DES_Update ..."
    ' From FIPS 81 Appendix C
    ' AN EXAMPLE OF THE CIPHER BLOCK CHAINING (CBC) MODE
        Dim nRet As Long
        Dim hContext As Long
        Dim sCorrect As String
        Dim abKey() As Byte
        Dim abInitV() As Byte
        Dim abBlock() As Byte
        Dim vntPlain(2) As Variant
        Dim vntCipher(2) As Variant
        Dim i As Integer
        
        sCorrect = "683788499a7c05f6"
        abKey = cnvBytesFromHexStr("0123456789abcdef")
        abInitV = cnvBytesFromHexStr("1234567890abcdef")
        Debug.Print "KY=" & cnvHexStrFromBytes(abKey)
        Debug.Print "IV=" & cnvHexStrFromBytes(abInitV)
        
        ' The plain text is the ASCII code for "Now is the time for all ".
        ' We will store in an array of arrays (!)
        vntPlain(0) = cnvBytesFromHexStr("4e6f772069732074")
        vntPlain(1) = cnvBytesFromHexStr("68652074696d6520")
        vntPlain(2) = cnvBytesFromHexStr("666f7220616c6c20")
        
        ' Initialise context
        hContext = DES_Init(abKey(0), ENCRYPT, "CBC", abInitV(0))
        If hContext = 0 Then
            nRet = DES_InitError()
            Debug.Print "DES_Init Failed: " & apiErrorLookup(nRet)
            Exit Sub
        End If
        
        For i = 0 To 2
            ' Get next block of plaintext from array
            abBlock = vntPlain(i)
            Debug.Print "PT(" & i & ")=" & cnvHexStrFromBytes(abBlock)
            nRet = DES_Update(hContext, abBlock(0), 8)
            Debug.Print "CT(" & i & ")=" & cnvHexStrFromBytes(abBlock)
            vntCipher(i) = abBlock
        Next
        Debug.Print "OK   =" & sCorrect
        
        ' Clear the context
        nRet = DES_Final(hContext)
        
        ' Now do in decrypt mode
        hContext = DES_Init(abKey(0), DECRYPT, "CBC", abInitV(0))
        If hContext = 0 Then
            nRet = DES_InitError()
            Debug.Print "DES_Init Failed: " & apiErrorLookup(nRet)
            Exit Sub
        End If
        
        For i = 0 To 2
            ' Get next block of ciphertext from array
            abBlock = vntCipher(i)
            Debug.Print "CT(" & i & ")=" & cnvHexStrFromBytes(abBlock)
            nRet = DES_Update(hContext, abBlock(0), 8)
            Debug.Print "PT(" & i & ")=" & cnvHexStrFromBytes(abBlock) & " [" & StrConv(abBlock, vbUnicode) & "]"
        Next
        nRet = DES_Final(hContext)
    

End Sub

Public Sub V_Test_DES_UpdateHex()
    Debug.Print "Testing DES_UpdateHex ..."
        Dim nRet As Long
        Dim hContext As Long
        Dim strKey As String
        Dim strHexString As String
        Dim sCorrect As String
    
        strKey = "0123456789abcdef"
        Debug.Print "KY=" & strKey
    
        ' Initialise the context
        hContext = DES_InitHex(strKey, True, "ECB", "")
        If hContext = 0 Then
            ' Always check for error
            MsgBox "Unable to initialise DES context", vbCritical
            Exit Sub
        End If
    
        strHexString = "4e6f772069732074"
        Debug.Print "PT=" & strHexString
        nRet = DES_UpdateHex(hContext, strHexString)
        Debug.Print "CT=" & strHexString
        Debug.Print "OK=" & "3fa40e8a984d4815"
    
        strHexString = "68652074696d6520666f7220616c6c20"
        Debug.Print "PT=" & strHexString
        nRet = DES_UpdateHex(hContext, strHexString)
        Debug.Print "CT=" & strHexString
        Debug.Print "OK=" & "6a271787ab8883f9893d51ec4b563b53"
    
        nRet = DES_Final(hContext)

End Sub

Public Sub V_Test_GCM_Encrypt()
    Debug.Print "Testing GCM_Encrypt ..."
    Dim abKey() As Byte
    Dim abPlain() As Byte
    Dim abAAD() As Byte
    Dim abIV() As Byte
    Dim abTag() As Byte
    Dim abCipher() As Byte
    Dim abCheck() As Byte
    Dim nKeyLen As Long
    Dim nDataLen As Long
    Dim nIvLen As Long
    Dim nAadLen As Long
    Dim nTagLen As Long
    Dim nRet As Long
    ' Test Case 4:
    ' Convert test vectors from hex to byte array format
    abKey = cnvBytesFromHexStr("feffe9928665731c6d6a8f9467308308")
    abPlain = cnvBytesFromHexStr("d9313225f88406e5a55909c5aff5269a" & _
        "86a7a9531534f7da2e4c303d8a318a72" & _
        "1c3c0c95956809532fcf0e2449a6b525" & _
        "b16aedf5aa0de657ba637b39")
    abAAD = cnvBytesFromHexStr("feedfacedeadbeeffeedfacedeadbeef" & _
        "abaddad2")
    abIV = cnvBytesFromHexStr("cafebabefacedbaddecaf888")
    ' and compute lengths
    nKeyLen = UBound(abKey) + 1
    nDataLen = UBound(abPlain) + 1
    nIvLen = UBound(abIV) + 1
    nAadLen = UBound(abAAD) + 1
    
    ' Dimension output arrays
    nTagLen = API_MAX_GMAC_BYTES
    ReDim abTag(nTagLen - 1)
    ReDim abCipher(nDataLen - 1)
    
    ' Do the business
    nRet = GCM_Encrypt(abCipher(0), nDataLen, abTag(0), nTagLen, _
        abPlain(0), nDataLen, _
        abKey(0), nKeyLen, abIV(0), nIvLen, abAAD(0), nAadLen, 0)
    Debug.Print "GCM_Encrypt returns " & nRet & " (expecting 0)"
    Debug.Print "CT =" & cnvHexStrFromBytes(abCipher)
    Debug.Print "TAG=" & cnvHexStrFromBytes(abTag)
    
    ' Check we can decrypt
    ReDim abCheck(nDataLen - 1)
    nRet = GCM_Decrypt(abCheck(0), nDataLen, abCipher(0), nDataLen, _
        abKey(0), nKeyLen, abIV(0), nIvLen, abAAD(0), nAadLen, _
        abTag(0), nTagLen, 0)
    Debug.Print "GCM_Decrypt returns " & nRet & " (expecting 0)"
    Debug.Print "PT'=" & cnvHexStrFromBytes(abCheck)
    Debug.Print "PT =" & cnvHexStrFromBytes(abPlain)

End Sub

Public Sub V_Test_GCM_Encrypt2()
    Debug.Print "Testing GCM_Encrypt ..."
    Dim abKey() As Byte
    Dim abAAD() As Byte
    Dim abIV() As Byte
    Dim abTag() As Byte
    Dim nKeyLen As Long
    Dim nAadLen As Long
    Dim nIvLen As Long
    Dim nTagLen As Long
    Dim nRet As Long
    ' Source: http://www.mail-archive.com/stds-p1619@listserv.ieee.org/msg00321.html
    ' KEY feffe9928665731c6d6a8f9467308308
    ' IV  cafebabefacedbaddecaf888
    ' AAD feedfacedeadbeeffeedfacedeadbeef
    ' TAG 54df474f4e71a9ef8a09bf30da7b1a92
    abKey = cnvBytesFromHexStr("feffe9928665731c6d6a8f9467308308")
    abIV = cnvBytesFromHexStr("cafebabefacedbaddecaf888")
    abAAD = cnvBytesFromHexStr("feedfacedeadbeeffeedfacedeadbeef")
    nKeyLen = UBound(abKey) + 1
    nIvLen = UBound(abIV) + 1
    nAadLen = UBound(abAAD) + 1
    
    Debug.Print "KEY " & cnvHexStrFromBytes(abKey)
    Debug.Print "IV  " & cnvHexStrFromBytes(abIV)
    Debug.Print "AAD " & cnvHexStrFromBytes(abAAD)
    
    ' Dimension output array
    nTagLen = API_MAX_GMAC_BYTES
    ReDim abTag(nTagLen - 1)
    
    ' GMAC := Encrypt with no CT output or PT input. GMAC value is in tag.
    nRet = GCM_Encrypt(0, 0, abTag(0), nTagLen, 0, 0, _
        abKey(0), nKeyLen, abIV(0), nIvLen, abAAD(0), nAadLen, 0)
    Debug.Print "TAG " & cnvHexStrFromBytes(abTag)
    Debug.Print "OK  " & "54df474f4e71a9ef8a09bf30da7b1a92"

End Sub

Public Sub V_Test_GCM_InitKey()
    Debug.Print "Testing GCM_InitKey ..."
    Dim abKey() As Byte
    Dim nKeyLen As Long
    Dim hContext As Long
    Dim nCode As Long
    
    ' Initialise with a valid key
    abKey = cnvBytesFromHexStr("feffe9928665731c6d6a8f9467308308")
    nKeyLen = UBound(abKey) + 1
    hContext = GCM_InitKey(abKey(0), nKeyLen, 0)
    Debug.Print "GCM_InitKey returns " & Hex(hContext) & " (expected non-0)"
    If hContext <> 0 Then
        '... do something here...
        ' Destroy the key
        Call GCM_FinishKey(hContext)
    End If
    
    ' Now try an invalid key (length must be 16,24, or 32 bytes)
    abKey = cnvBytesFromHexStr("badace")
    nKeyLen = UBound(abKey) + 1
    hContext = GCM_InitKey(abKey(0), nKeyLen, 0)
    Debug.Print "GCM_InitKey returns " & Hex(hContext)
    ' Use API_ErrorCode to find the error value
    nCode = API_ErrorCode()
    Debug.Print "API_ErrorCode returns " & nCode & ": " & apiErrorLookup(nCode)

End Sub

Public Sub V_Test_HASH_Bytes()
    Debug.Print "Testing HASH_Bytes ..."
    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(API_MAX_HASH_BYTES - 1)
    
    ' Create default hash (SHA-1)
    nRet = HASH_Bytes(abDigest(0), API_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(API_MAX_HASH_BYTES - 1)
    nRet = HASH_Bytes(abDigest(0), API_MAX_HASH_BYTES, abMessage(0), nMsgLen, API_HASH_MD5)
    If nRet > 0 Then ReDim Preserve abDigest(nRet - 1)
    Debug.Print nRet, cnvHexStrFromBytes(abDigest)
    
    ' Repeat for SHA-3-384
    ReDim abDigest(API_MAX_HASH_BYTES - 1)
    nRet = HASH_Bytes(abDigest(0), API_MAX_HASH_BYTES, abMessage(0), nMsgLen, API_HASH_SHA3_384)
    If nRet > 0 Then ReDim Preserve abDigest(nRet - 1)
    Debug.Print nRet, cnvHexStrFromBytes(abDigest)

End Sub

Public Sub V_Test_HASH_File()
    Debug.Print "Testing HASH_File ..."
        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(API_MAX_HASH_BYTES)
        
        ' Create default hash (SHA1) in binary mode
        nRet = HASH_File(abDigest(0), API_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(API_MAX_HASH_BYTES)
        nRet = HASH_File(abDigest(0), API_MAX_HASH_BYTES, sFileName, API_HASH_MODE_TEXT)
        If nRet > 0 Then ReDim Preserve abDigest(nRet - 1)
        Debug.Print nRet, cnvHexStrFromBytes(abDigest)
        
        ' Use MD5
        ReDim abDigest(API_MAX_HASH_BYTES)
        nRet = HASH_File(abDigest(0), API_MAX_HASH_BYTES, sFileName, API_HASH_MD5)
        If nRet > 0 Then ReDim Preserve abDigest(nRet - 1)
        Debug.Print nRet, cnvHexStrFromBytes(abDigest)
        
        ' Use MD5 in "text" mode
        ReDim abDigest(API_MAX_HASH_BYTES)
        nRet = HASH_File(abDigest(0), API_MAX_HASH_BYTES, sFileName, API_HASH_MD5 Or API_HASH_MODE_TEXT)
        If nRet > 0 Then ReDim Preserve abDigest(nRet - 1)
        Debug.Print nRet, cnvHexStrFromBytes(abDigest)

End Sub

Public Sub V_Test_HASH_HexFromBits()
    Debug.Print "Testing HASH_HexFromBits ..."
    Dim strDigest As String
    Dim nRet As Long
    Dim abData() As Byte
    Dim nDataBitLen As Long
    
    ' SHA-1
    strDigest = String(API_SHA1_CHARS, " ")
    abData = cnvBytesFromHexStr("5180")
    nDataBitLen = 9
    Debug.Print "[SHA-1]"
    Debug.Print "[L = " & API_SHA1_BYTES & "]"
    Debug.Print "Len = " & nDataBitLen
    Debug.Print "Msg = " & cnvHexStrFromBytes(abData)
    nRet = HASH_HexFromBits(strDigest, Len(strDigest), abData(0), nDataBitLen, API_HASH_SHA1)
    Debug.Print "MD = " & strDigest

End Sub

Public Sub V_Test_HASH_HexFromBits2()
    Debug.Print "Testing HASH_HexFromBits ..."
    ' Ref: SHAVS-SHA3 CAVS 19.0 "SHA3-256 ShortMsg" information for "SHA3AllBits1-28-16"
    ' Len = 22
    ' Msg = 259028*
    ' MD = d5863d4b1ff41551c92a9e08c52177e32376c9bd100c611c607db840096eb22f
    
    ' * NB NIST convention for bit strings is different from CryptoSys API
    ' NIST "259028" => API "2590A0"
    
    Dim strDigest As String
    Dim nRet As Long
    Dim abData() As Byte
    Dim nDataBitLen As Long
    
    strDigest = String(API_SHA256_CHARS, " ")
    abData = cnvBytesFromHexStr("2590A0")
    nDataBitLen = 22
    Debug.Print "[L = " & API_SHA256_BYTES * 8 & "]"
    Debug.Print "Len = " & nDataBitLen
    Debug.Print "Msg = " & cnvHexStrFromBytes(abData)
    nRet = HASH_HexFromBits(strDigest, Len(strDigest), abData(0), nDataBitLen, API_HASH_SHA3_256)
    Debug.Print "MD = " & strDigest

End Sub

Public Sub V_Test_HASH_HexFromBytes()
    Debug.Print "Testing HASH_HexFromBytes ..."
    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(API_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, API_HASH_SHA1)
    Debug.Print nRet, Left(sDigest, nRet)
    ' Pre-dimension digest string and use MD5
    sDigest = String(API_MD5_CHARS, " ")
    nRet = HASH_HexFromBytes(sDigest, Len(sDigest), abMessage(0), 3, API_HASH_MD5)
    Debug.Print nRet, sDigest
    ' Pre-dimension digest string and use MD2
    sDigest = String(API_MD5_CHARS, " ")
    nRet = HASH_HexFromBytes(sDigest, Len(sDigest), abMessage(0), 3, API_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, API_HASH_SHA1)
    Debug.Print nRet, sDigest

End Sub

Public Sub V_Test_HASH_HexFromBytes2()
    Debug.Print "Testing HASH_HexFromBytes ..."
    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_HexFromFile()
    Debug.Print "Testing HASH_HexFromFile ..."
    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(API_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, API_HASH_MODE_TEXT)
    Debug.Print nRet, Left(sDigest, nRet)
    ' Use MD5
    nRet = HASH_HexFromFile(sDigest, Len(sDigest), sFileName, API_HASH_MD5)
    Debug.Print nRet, Left(sDigest, nRet)
    ' Use MD5 in "text" mode
    nRet = HASH_HexFromFile(sDigest, Len(sDigest), sFileName, API_HASH_MD5 Or API_HASH_MODE_TEXT)
    Debug.Print nRet, Left(sDigest, nRet)

End Sub

Public Sub V_Test_HASH_HexFromHex()
    Debug.Print "Testing HASH_HexFromHex ..."
    Dim strDigest As String
    Dim nRet As Long
    Dim strData As String
    strDigest = String(API_SHA1_CHARS, " ")
    strData = "616263"
    nRet = HASH_HexFromHex(strDigest, Len(strDigest), strData, API_HASH_SHA1)
    Debug.Print strDigest

End Sub

Public Sub V_Test_MAC_Bytes()
    Debug.Print "Testing MAC_Bytes ..."
    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 = API_SHA1_BYTES
    ReDim abDigest(nDigLen - 1)
    nRet = MAC_Bytes(abDigest(0), nDigLen, abData(0), nDataLen, abKey(0), nKeyLen, API_HASH_SHA1)
    If nRet <= 0 Then Exit Sub ' ERROR
    Debug.Print "HMAC-SHA-1  =" & cnvHexStrFromBytes(abDigest)
    Debug.Print "CORRECT     =" & "4c9007f4026250c6bc8414f9bf50c86c2d7235da"
    
    ' Compute HMAC-MD5
    nDigLen = API_MD5_BYTES
    ReDim abDigest(nDigLen - 1)
    nRet = MAC_Bytes(abDigest(0), nDigLen, abData(0), nDataLen, abKey(0), nKeyLen, API_HASH_MD5)
    If nRet <= 0 Then Exit Sub ' ERROR
    Debug.Print "HMAC-MD5    =" & cnvHexStrFromBytes(abDigest)
    Debug.Print "CORRECT     =" & "697eaf0aca3a3aea3a75164746ffaa79"
    
    ' Compute HMAC-SHA-256
    nDigLen = API_SHA256_BYTES
    ReDim abDigest(nDigLen - 1)
    nRet = MAC_Bytes(abDigest(0), nDigLen, abData(0), nDataLen, abKey(0), nKeyLen, API_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_MAC_HexFromBytes()
    Debug.Print "Testing MAC_HexFromBytes ..."
    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(API_MAX_HASH_CHARS, " ")
    
    ' Compute default HMAC (HMAC-SHA-1)
    nRet = MAC_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(API_MAX_HASH_CHARS, " ")
    nRet = MAC_HexFromBytes(strDigest, Len(strDigest), abData(0), nDataLen, abKey(0), nKeyLen, API_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(API_MAX_HASH_CHARS, " ")
    nRet = MAC_HexFromBytes(strDigest, Len(strDigest), abData(0), nDataLen, abKey(0), nKeyLen, API_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(API_MAX_HASH_CHARS, " ")
    nRet = MAC_HexFromBytes(strDigest, Len(strDigest), abData(0), nDataLen, abKey(0), nKeyLen, API_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_MAC_HexFromHex()
    Debug.Print "Testing MAC_HexFromHex ..."
    Dim strKeyHex As String
    Dim strMsgHex As String
    Dim strMAC As String
    Dim nRet As Long
    
    ' SP800-38: compute CMAC_AES-128 on Example 2: Mlen = 128
    strKeyHex = "2b7e151628aed2a6abf7158809cf4f3c"
    strMsgHex = "6bc1bee22e409f96e93d7e117393172a"
    ' Output MAC size in hex is double the block length of the cipher
    strMAC = String(API_BLK_AES_BYTES * 2, " ")
    nRet = MAC_HexFromHex(strMAC, Len(strMAC), strMsgHex, strKeyHex, API_CMAC_AES128)
    If nRet > 0 Then
        Debug.Print "CMAC-AES-128(K128, M128)=" & Left$(strMAC, nRet)
    Else
        Debug.Print "Error code " & nRet
    End If

End Sub

Public Sub V_Test_MAC_HexFromHex2()
    Debug.Print "Testing MAC_HexFromHex ..."
    ' Ref: Test vector from `draft-irtf-cfrg-chacha20-poly1305-06.txt`
    Dim nRet As Long
    Dim strDigest As String
    Dim strMsgHex As String
    
    ' Convert ASCII message string to hex format
    strMsgHex = cnvHexStrFromString("Cryptographic Forum Research Group")
    ' Dimension digest string to receive 32 characters
    strDigest = String(API_POLY1305_CHARS, " ")
    ' Create authentication tag using 256-bit key material
    nRet = MAC_HexFromHex(strDigest, Len(strDigest), strMsgHex, _
        "85d6be7857556d337f4452fe42d506a80103808afb0db2fd4abff6af4149f51b", API_MAC_POLY1305)
    Debug.Print "Poly1305 Tag: " & strDigest

End Sub

Public Sub V_Test_MAC_HexFromHex3()
    Debug.Print "Testing MAC_HexFromHex ..."
    ' Ref: NIST Computer Security Division
    ' "Keyed-Hash Message Authentication Code (HMAC) - using SHA3-256"
    ' `HMAC_SHA3-256.pdf` 2016-03-28
    Dim strText As String
    Dim strKeyHex As String
    Dim strMsgHex As String
    Dim strMAC As String
    Dim nLen As Long
    'Sample #1 Block length = 136, Key length = 32, Tag length = 32
    strText = "Sample message for keylen<blocklen"
    strKeyHex = "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f"
    strMsgHex = cnvHexStrFromString(strText)
    Debug.Print "Text is " & strMsgHex
    Debug.Print "Key is " & strKeyHex
    ' Get required output length
    nLen = MAC_HexFromHex("", 0, strMsgHex, strKeyHex, API_HASH_SHA3_256)
    strMAC = String(nLen, " ")
    nLen = MAC_HexFromHex(strMAC, Len(strMAC), strMsgHex, strKeyHex, API_HASH_SHA3_256)
    Debug.Print "Mac is " & strMAC

End Sub

Public Sub V_Test_MD5_AddBytes()
    Debug.Print "Testing MD5_AddBytes ..."
        Dim nRet As Long
        Dim strDigest As String
        Dim hContext As Long
        Dim abData(2) As Byte
    
        ' Set context handle
        hContext = MD5_Init()
        ' Remember to check for an invalid handle
        If hContext = 0 Then
            MsgBox "Failed to set context"
            Exit Sub
        End If
    
        ' Set up a test array of bytes
        abData(0) = Asc("a")
        abData(1) = &H62    ' same as Asc("b")
        ' Add mixture of bytes and strings
        nRet = MD5_AddBytes(hContext, abData(0), 2)
        nRet = MD5_AddString(hContext, "c")
    
        ' Set strDigest to be 32 chars
        strDigest = String(32, " ")
        nRet = MD5_HexDigest(strDigest, hContext)
        Debug.Print strDigest

End Sub

Public Sub V_Test_MD5_AddString()
    Debug.Print "Testing MD5_AddString ..."
        Dim nRet As Long
        Dim strDigest As String
        Dim hContext As Long
        Dim i As Long
        Dim sA1000 As String
    
        ' Set context handle
        hContext = MD5_Init()
        If hContext = 0 Then
            MsgBox "Failed to set context"
            Exit Sub
        End If
    
        ' Create a string of 1000 'a's
        sA1000 = String(1000, "a")
    
        ' Add 1000 times => one million repetitions of "a"
        For i = 1 To 1000
            nRet = MD5_AddString(hContext, sA1000)
        Next
    
        ' Set strDigest to be 32 chars - don't forget!!
        strDigest = String(32, " ")
        nRet = MD5_HexDigest(strDigest, hContext)
        Debug.Print strDigest

End Sub

Public Sub V_Test_MD5_BytesHash()
    Debug.Print "Testing MD5_BytesHash ..."
        Dim nRet As Long
        Dim abData(2) As Byte   ' Create 3-byte array (NB zero-based)
        Dim abDigest(15) As Byte ' Create 16-byte array to receive digest
        
        ' Setup byte array with "abc"
        abData(0) = Asc("a")
        abData(1) = Asc("b")
        abData(2) = Asc("c")
        
        ' Compute MD5 hash digest
        nRet = MD5_BytesHash(abDigest(0), abData(0), 3)
        
        ' Print resulting bytes in hex format
        Debug.Print nRet; cnvHexStrFromBytes(abDigest)

End Sub

Public Sub V_Test_MD5_BytesHash2()
    Debug.Print "Testing MD5_BytesHash ..."
        Dim nRet As Long
        Dim abData(2) As Byte   ' Create 3-byte array (NB zero-based)
        Dim abDigest(15) As Byte ' Create 16-byte array to receive digest
        Dim i As Integer
        
        ' Setup byte array with "abc"
        abData(0) = Asc("a")
        abData(1) = Asc("b")
        abData(2) = Asc("c")
        
        ' Compute MD5 hash digest of input
        nRet = MD5_BytesHash(abDigest(0), abData(0), 3)
        
        ' Now carry out repeated hashes of the 16-byte-long digest
        For i = 2 To 1000
            nRet = MD5_BytesHash(abDigest(0), abDigest(0), 16)
        Next
       
        ' Print H(1000) in hex format
        Debug.Print cnvHexStrFromBytes(abDigest)

End Sub

Public Sub V_Test_MD5_BytesHexHash()
    Debug.Print "Testing MD5_BytesHexHash ..."
        Dim nRet As Long
        Dim abData(2) As Byte   ' Create 3-byte array (NB zero-based)
        ' Alternative way of making sure string is 32 chars long
        Dim strDigest As String * 32
    
        ' Setup byte array with "abc"
        abData(0) = Asc("a")
        abData(1) = Asc("b")
        abData(2) = Asc("c")
    
        nRet = MD5_BytesHexHash(strDigest, abData(0), 3)
        Debug.Print nRet; strDigest

End Sub

Public Sub V_Test_MD5_FileHexHash()
    Debug.Print "Testing MD5_FileHexHash ..."
        Dim nRet As Long
        Dim strDigest As String
        Dim strFileName As String
    
        strFileName = "hello.txt"
        ' Set strDigest to be 32 chars
        strDigest = String(32, " ")
        ' Make md5sum in text mode (treating CR-LF as single NL)
        nRet = MD5_FileHexHash(strDigest, strFileName, "t")
        Debug.Print "t " & nRet; strDigest
        ' Do in binary mode (treating CR-LF as two binary bytes)
        nRet = MD5_FileHexHash(strDigest, strFileName, "b")
        Debug.Print "b " & nRet; strDigest

End Sub

Public Sub V_Test_MD5_Hmac()
    Debug.Print "Testing MD5_Hmac ..."
        Dim nRet As Long
        Dim abData() As Byte
        Dim abKey() As Byte
        Dim i As Integer
        Dim nDataLen As Long, nKeyLen As Long
        Dim strDigest As String * 32
    
        ' Test No 1.
        ' Set key = 0x0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b
        ReDim abKey(15)
        For i = 0 To 15
            abKey(i) = &HB
        Next
        ' Convert string to byte array
        abData() = StrConv("Hi There", vbFromUnicode)
        nDataLen = UBound(abData) + 1
        ' Create HMAC digest
        nRet = MD5_Hmac(strDigest, abData(0), nDataLen, abKey(0), 16)
        Debug.Print 1; nRet; strDigest
    
        ' Test No 2.
        abKey() = StrConv("Jefe", vbFromUnicode)
        nKeyLen = UBound(abKey) + 1
        abData() = StrConv("what do ya want for nothing?", vbFromUnicode)
        nDataLen = UBound(abData) + 1
        nRet = MD5_Hmac(strDigest, abData(0), nDataLen, abKey(0), nKeyLen)
        Debug.Print 2; nRet; strDigest
    
        ' Test No 3.
        ReDim abKey(15)
        For i = 0 To 15
            abKey(i) = &HAA
        Next
        ReDim abData(49)
        For i = 0 To 49
            abData(i) = &HDD
        Next
        nRet = MD5_Hmac(strDigest, abData(0), 50, abKey(0), 16)
        Debug.Print 3; nRet; strDigest

End Sub

Public Sub V_Test_MD5_HmacHex()
    Debug.Print "Testing MD5_HmacHex ..."
    '    Test No 1. from RFC 2104
    '    key =         0x0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b
    '    key_len =     16 bytes
    '    Data = "Hi There"
    '    data_len =    8  bytes
    '    digest =      0x9294727a3638bb1c13f48ef8158bfc9d
    
        Dim nRet As Long
        Dim strDigest As String * 32
        Dim strMessage As String
        Dim sHexMsg As String
        Dim sCorrect As String
        
        sCorrect = "9294727a3638bb1c13f48ef8158bfc9d"
        
        ' Convert data to hex format
        sHexMsg = cnvHexStrFromString("Hi There")
        nRet = MD5_HmacHex(strDigest, sHexMsg, "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b")
        Debug.Print "Digest =" & strDigest
        Debug.Print "Correct=" & sCorrect
        Debug.Assert (strDigest = sCorrect)

End Sub

Public Sub V_Test_MD5_Reset()
    Debug.Print "Testing MD5_Reset ..."
        Dim nRet As Long
        Dim hContext As Long
    
        hContext = MD5_Init()
        nRet = MD5_Reset(hContext)

End Sub

Public Sub V_Test_MD5_StringHexHash()
    Debug.Print "Testing MD5_StringHexHash ..."
        Dim nRet As Long
        Dim strDigest As String
        ' Set strDigest to be 32 chars
        strDigest = String(32, " ")
        nRet = MD5_StringHexHash(strDigest, "abc")
        Debug.Print strDigest
    
        nRet = MD5_StringHexHash(strDigest, _
            "abcdefghijklmnopqrstuvwxyz")
        Debug.Print strDigest

End Sub

Public Sub V_Test_PAD_BytesBlock()
    Debug.Print "Testing PAD_BytesBlock ..."
    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
    
    ' Re-dimension the output to the correct length
    ReDim Preserve abOutput(nOutputLen - 1)
    Debug.Print "Unpadded data=0x" & cnvHexStrFromBytes(abOutput)

End Sub

Public Sub V_Test_PAD_HexBlock()
    Debug.Print "Testing PAD_HexBlock ..."
    Dim strInputHex As String
    Dim strOutputHex As String
    Dim nOutChars As Long
    Dim nBlockLen As Long
    
    ' Prepare test input 3 bytes long
    strInputHex = "FFFFFF"
    Debug.Print "Input data='" & strInputHex & "'"
    ' Find out the required number of characters in output (the same for all schemes)
    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, " ")
    ' Add default padding (PKCS5Padding)
    nOutChars = PAD_HexBlock(strOutputHex, Len(strOutputHex), strInputHex, nBlockLen, 0)
    Debug.Print "Padded data='" & strOutputHex & "'"
    ' Add OneAndZeroesPadding
    nOutChars = PAD_HexBlock(strOutputHex, Len(strOutputHex), strInputHex, nBlockLen, API_PAD_1ZERO)
    Debug.Print "Padded data='" & strOutputHex & "'"
    ' Add ANSIX9.23 Padding
    nOutChars = PAD_HexBlock(strOutputHex, Len(strOutputHex), strInputHex, nBlockLen, API_PAD_AX923)
    Debug.Print "Padded data='" & strOutputHex & "'"

End Sub

Public Sub V_Test_PAD_HexBlock2()
    Debug.Print "Testing PAD_HexBlock ..."
    Dim strInputHex As String
    Dim strOutputHex As String
    ' Pad an empty string
    Debug.Print "Input data= '" & strInputHex & "'"
    ' Pad for Triple DES block
    strOutputHex = padHexString(strInputHex, API_BLK_TDEA_BYTES)
    Debug.Print "Padded data='" & strOutputHex & "'"
    ' Prepare test input 5 bytes long
    strInputHex = "FFFFFFFFFF"
    Debug.Print "Input data= '" & strInputHex & "'"
    ' Pad for Triple DES block
    strOutputHex = padHexString(strInputHex, API_BLK_TDEA_BYTES)
    Debug.Print "Padded data='" & strOutputHex & "'"

End Sub

Public Sub V_Test_PAD_UnpadHex()
    Debug.Print "Testing PAD_UnpadHex ..."
    Dim strInputHex As String
    Dim strOutputHex As String
    strInputHex = "FFFFFFFFFF030303"
    Debug.Print "Input data= '" & strInputHex & "'"
    strOutputHex = unpadHexString(strInputHex, API_BLK_TDEA_BYTES)
    Debug.Print "Result=     '" & strOutputHex & "'"
    strInputHex = "0808080808080808"
    Debug.Print "Input data= '" & strInputHex & "'"
    strOutputHex = unpadHexString(strInputHex, API_BLK_TDEA_BYTES)
    Debug.Print "Result=     '" & strOutputHex & "'"
    ' Bad input data results in the same data being returned
    strInputHex = "FFFFFFFFFFFFFFFF"
    Debug.Print "Input data= '" & strInputHex & "'"
    strOutputHex = unpadHexString(strInputHex, API_BLK_TDEA_BYTES)
    Debug.Print "Result=     '" & strOutputHex & "'"
    If Len(strOutputHex) = Len(strInputHex) Then
        Debug.Print "DECRYPTION ERROR"
    End If

End Sub

Public Sub V_Test_PBE_Kdf2()
    Debug.Print "Testing PBE_Kdf2 ..."
        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 ..."
        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, API_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, API_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, API_HASH_SHA224)
        Debug.Print "Derived key {HMAC-SHA-224} = " & cnvHexStrFromBytes(abDerivedKey)

End Sub

Public Sub V_Test_PBE_Kdf2Hex()
    Debug.Print "Testing PBE_Kdf2Hex ..."
    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_Scrypt()
    Debug.Print "Testing PBE_Scrypt ..."
    Dim abPwd() As Byte
    Dim abSalt() As Byte
    Dim abDK() As Byte
    Dim nKeyLen As Long
    Dim nPwdlen As Long
    Dim nSaltLen As Long
    Dim nRet As Long
    
    nKeyLen = 64
    ' Dimension key byte array
    ReDim abDK(nKeyLen - 1)
    ' Convert strings to byte array form
    abPwd = StrConv("password", vbFromUnicode)
    abSalt = StrConv("NaCl", vbFromUnicode)
    ' Get lengths in bytes
    nPwdlen = UBound(abPwd) + 1
    nSaltLen = UBound(abSalt) + 1
    ' Call the SCRYPT function to derive a 64-byte key with parameters N=1024, r=8, p=16
    nRet = PBE_Scrypt(abDK(0), nKeyLen, abPwd(0), nPwdlen, abSalt(0), nSaltLen, 1024, 8, 16, 0)
    Debug.Print "PBE_Scrypt() returns " & nRet & " (expecting 0)"
    Debug.Print "KEY=" & cnvHexStrFromBytes(abDK)

End Sub

Public Sub V_Test_PBE_ScryptHex()
    Debug.Print "Testing PBE_ScryptHex ..."
    Dim strDerivedKey As String
    Dim nKeyLen As Long
    Dim strPassword As String
    Dim strSaltHex As String
    Dim nRet As Long
    
    strPassword = "pleaseletmein"  ' NB normal text, not hex
    strSaltHex = cnvHexStrFromString("SodiumChloride")
    
    ' Pre-dimension output string for derived key to
    ' required length of two times number of bytes
    ' (Don't forget to do this)
    nKeyLen = 64
    strDerivedKey = String(2 * nKeyLen, " ")
    
    ' Derive key using SCRYPT
    nRet = PBE_ScryptHex(strDerivedKey, Len(strDerivedKey), nKeyLen, _
        strPassword, strSaltHex, 16384, 8, 1, 0)
    
    Debug.Print "Derived key = " & strDerivedKey

End Sub

Public Sub V_Test_PC1_Bytes()
    Debug.Print "Testing PC1_Bytes ..."
        Dim abKey() As Byte
        Dim abInput() As Byte
        Dim abOutput() As Byte
        Dim nRet As Long
        Dim nDataLen As Long
        Dim nKeyLen As Long
        Dim sCorrect As String
        
        abKey = cnvBytesFromHexStr("0123456789abcdef")
        abInput = cnvBytesFromHexStr("0123456789abcdef")
        sCorrect = "75b7878099e0c596"
        
        ReDim abOutput(UBound(abInput))
        nDataLen = UBound(abInput) - LBound(abInput) + 1
        nKeyLen = UBound(abKey) - LBound(abKey) + 1
        
        Debug.Print "KY=" & cnvHexStrFromBytes(abKey)
        Debug.Print "PT=" & cnvHexStrFromBytes(abInput)
        ' Encipher using PC1
        nRet = PC1_Bytes(abOutput(0), abInput(0), nDataLen, abKey(0), nKeyLen)
        Debug.Print "CT=" & cnvHexStrFromBytes(abOutput)
        Debug.Print "OK=" & sCorrect
        
        ' Now decipher just by calling again. Use same output as input.
        nRet = PC1_Bytes(abOutput(0), abOutput(0), nDataLen, abKey(0), nKeyLen)
        Debug.Print "P'=" & cnvHexStrFromBytes(abOutput)

End Sub

Public Sub V_Test_PC1_File()
    Debug.Print "Testing PC1_File ..."
        Const MY_PATH As String = ""
        Dim abKey(5) As Byte
        Dim strFileOut As String
        Dim strFileIn As String
        Dim strFileChk As String
        Dim nRet As Long
    
        Debug.Print "Test_PC1_File..."
        ' Construct full path names to files
        strFileIn = MY_PATH & "hello.txt"
        strFileOut = MY_PATH & "hello.pc1.enc.dat"
        strFileChk = MY_PATH & "hello.pc1.chk.txt"
    
        ' Setup the 6-byte key "abcxyz"
        abKey(0) = Asc("a")
        abKey(1) = Asc("b")
        abKey(2) = Asc("c")
        abKey(3) = Asc("x")
        abKey(4) = Asc("y")
        abKey(5) = Asc("z")
    
        ' Encipher plaintext file
        nRet = PC1_File(strFileOut, strFileIn, abKey(0), 6&)
        Debug.Print "PC1_File returns " & nRet
    
        ' Now decipher just by repeating
        nRet = PC1_File(strFileChk, strFileOut, abKey(0), 6&)
        Debug.Print "PC1_File returns " & nRet

End Sub

Public Sub V_Test_PC1_Hex()
    Debug.Print "Testing PC1_Hex ..."
        Dim nRes As Long
        Dim strKey As String
        Dim strInput As String
        Dim strOutput As String
        Dim strCorrect As String
        Dim strCheck As String
        
        ' Test vector 3
        strKey = "ef012345"
        strInput = "00000000000000000000"
        strCorrect = "d6a141a7ec3c38dfbd61"
        
        Debug.Print "KY=" & strKey
        Debug.Print "PT=" & strInput
        ' Encipher using PC1 in hex mode
        strOutput = String(Len(strInput), " ")
        nRes = PC1_Hex(strOutput, Len(strOutput), strInput, strKey)
        Debug.Print "CT=" & strOutput
        Debug.Print "OK=" & strCorrect
        
        ' Now decipher just by calling again.
        strCheck = String(Len(strInput), " ")
        nRes = PC1_Hex(strCheck, Len(strCheck), strOutput, strKey)
        Debug.Print "P'=" & strCheck

End Sub

Public Sub V_Test_RNG_Initialize()
    Debug.Print "Testing RNG_Initialize ..."
    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_KeyBytes(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_KeyBytes()
    Debug.Print "Testing RNG_KeyBytes ..."
        Dim abKey() As Byte
        Dim nRet As Long
        Dim nKeyBytes As Long
        Dim i As Integer
        
        nKeyBytes = 24
        ReDim abKey(nKeyBytes - 1)
        ' Generate three successive 192-bit random keys with no seeding
        For i = 1 To 3
            nRet = RNG_KeyBytes(abKey(0), nKeyBytes, "", 0)
            Debug.Print cnvHexStrFromBytes(abKey)
        Next

End Sub

Public Sub V_Test_RNG_KeyHex()
    Debug.Print "Testing RNG_KeyHex ..."
        Dim strHexKey As String
        Dim nRet As Long
        Dim nKeyBytes As Long
        Dim strSeed As String
        Dim i As Integer
        
        nKeyBytes = 24
        ' Pre-dimension hex string to be DOUBLE key length in bytes
        strHexKey = String(nKeyBytes * 2, " ")
        
        nRet = RNG_KeyHex(strHexKey, Len(strHexKey), nKeyBytes, "", 0)
        Debug.Print strHexKey
        
        ' Generate three successive 192-bit random keys with no seeding
        For i = 1 To 3
            nRet = RNG_KeyHex(strHexKey, Len(strHexKey), nKeyBytes, "", 0)
            Debug.Print strHexKey
        Next
        
        ' Generate three more 192-bit random keys using the counter as a seed
        For i = 1 To 3
            strSeed = CStr(i)
            nRet = RNG_KeyHex(strHexKey, Len(strHexKey), nKeyBytes, strSeed, Len(strSeed))
            Debug.Print strHexKey
        Next
        
        ' Generate a DES key and check if it's a weak key
        strHexKey = String(8 * 2, " ")
        nRet = RNG_KeyHex(strHexKey, Len(strHexKey), 8, "", 0)
        Debug.Print strHexKey
        nRet = DES_CheckKeyHex(strHexKey)
        Debug.Print "DES_CheckKeyHex returns " & nRet & " (" & apiErrorLookup(nRet) & ")"
        
        ' Test a known weak key
        strHexKey = "fefefefefefefefe"
        nRet = DES_CheckKeyHex(strHexKey)
        Debug.Print "DES_CheckKeyHex returns " & nRet & " (" & apiErrorLookup(nRet) & ")"

End Sub

Public Sub V_Test_RNG_NonceData()
    Debug.Print "Testing RNG_NonceData ..."
        Dim abKey() As Byte
        Dim nRet As Long
        Dim nKeyBytes As Long
        Dim i As Integer
        
        nKeyBytes = 8
        ReDim abKey(nKeyBytes - 1)
        ' Generate three successive 8-byte nonces
        For i = 1 To 3
            nRet = RNG_NonceData(abKey(0), nKeyBytes)
            Debug.Print cnvHexStrFromBytes(abKey)
        Next

End Sub

Public Sub V_Test_RNG_NonceDataHex()
    Debug.Print "Testing RNG_NonceDataHex ..."
        Dim sHexData As String
        Dim nRet As Long
        Dim nBytes As Long
    
        nBytes = 20
        ' Set hex string length to 2 x # bytes required.
        sHexData = String(2 * nBytes, " ")
        nRet = RNG_NonceDataHex(sHexData, Len(sHexData), nBytes)
        Debug.Print sHexData

End Sub

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

End Sub

Public Sub V_Test_RNG_Test()
    Debug.Print "Testing RNG_Test ..."
        Dim nRet As Long
        nRet = RNG_Test("Fips140t.txt")

End Sub

Public Sub V_Test_RNG_TestDRBGVS()
    Debug.Print "Testing RNG_TestDRBGVS ..."
    Dim nRet As Long
    Dim strOutput As String
    Dim nMaxChars As Long
    ' Set input values in hex
    Const nReturnedBitsLen As Long = 160
    Const strEntropyInput As String = "329a2a877b897cf6cb95d54017fe4770"
    Const strNonce As String = "16d8e0c752cf4a25"
    Const strPersonalizationString As String = "3535a9a540be9bd156dd440072f7d35e"
    Const strAdditionalInput1 As String = "1b2c842d4a898f6919f1f3dbbbe3aaea"
    Const strEntropyReseed As String = "9075150495f1ba810c37946f86526d9c"
    Const strAdditionalInputReseed As String = "5b40ba5f1770f04bdfc9979279c58228"
    Const strAdditionalInput2 As String = "97c88090b3aa6e60ea837ae38acaa47f"
    
    ' Print output details
    Debug.Print "# HMAC_DRBG options: SHA-1"
    Debug.Print "[SHA-1]"
    Debug.Print "[PredictionResistance = False]"
    
    Debug.Print "[EntropyInputLen = " & Len(strEntropyInput) * 8 / 2 & "]"
    Debug.Print "[NonceLen = " & Len(strNonce) * 8 / 2 & "]"
    Debug.Print "[PersonalizationStringLen = " & Len(strPersonalizationString) * 8 / 2 & "]"
    Debug.Print "[AdditionalInputLen = " & Len(strAdditionalInput1) * 8 / 2 & "]"
    Debug.Print
    Debug.Print "EntropyInput = 329a2a877b897cf6cb95d54017fe4770"
    Debug.Print "Nonce = 16d8e0c752cf4a25"
    Debug.Print "PersonalizationString = 3535a9a540be9bd156dd440072f7d35e"
    Debug.Print "AdditionalInput = 1b2c842d4a898f6919f1f3dbbbe3aaea"
    Debug.Print "EntropyInputReseed = 9075150495f1ba810c37946f86526d9c"
    Debug.Print "AdditionalInputReseed = 5b40ba5f1770f04bdfc9979279c58228"
    Debug.Print "AdditionalInput = 97c88090b3aa6e60ea837ae38acaa47f"
    
    ' Perform the DRBGVS test, dimensioning output string first
    strOutput = String(nReturnedBitsLen * 2 / 8, " ")
    nRet = RNG_TestDRBGVS(strOutput, Len(strOutput), nReturnedBitsLen, strEntropyInput, strNonce, _
      strPersonalizationString, strAdditionalInput1, _
      strEntropyReseed, strAdditionalInputReseed, strAdditionalInput2, 0)
    Debug.Print "ReturnedBits = " & strOutput

End Sub

Public Sub V_Test_SHA1_AddBytes()
    Debug.Print "Testing SHA1_AddBytes ..."
        Dim nRet As Long
        Dim strDigest As String
        Dim hContext As Long
        Dim abData(2) As Byte
    
        ' Set context handle
        hContext = SHA1_Init()
        ' Remember to check for an invalid handle
        If hContext = 0 Then
            MsgBox "Failed to set context"
            Exit Sub
        End If
    
        ' Set up a test array of bytes
        abData(0) = Asc("a")
        abData(1) = &H62    ' same as Asc("b")
        ' Add mixture of bytes and strings
        nRet = SHA1_AddBytes(hContext, abData(0), 2)
        nRet = SHA1_AddString(hContext, "c")
    
        ' Set strDigest to be 40 chars
        strDigest = String(40, " ")
        nRet = SHA1_HexDigest(strDigest, hContext)
        Debug.Print strDigest

End Sub

Public Sub V_Test_SHA1_AddString()
    Debug.Print "Testing SHA1_AddString ..."
        Dim nRet As Long
        Dim strDigest As String
        Dim hContext As Long
    
        ' Set context handle
        hContext = SHA1_Init()
    
        Debug.Print "SHA1_Init() returns handle = " & Hex(hContext)
        ' Remember to check for an invalid handle
        If hContext = 0 Then
            MsgBox "Failed to set context"
            Exit Sub
        End If
    
        ' Add strings one by one
        nRet = SHA1_AddString(hContext, "a")
        nRet = SHA1_AddString(hContext, "bc")
    
        ' Set strDigest to be 40 chars
        strDigest = String(40, " ")
        nRet = SHA1_HexDigest(strDigest, hContext)
        Debug.Print strDigest

End Sub

Public Sub V_Test_SHA1_BytesHash()
    Debug.Print "Testing SHA1_BytesHash ..."
        Dim nRet As Long
        Dim abData(2) As Byte   ' Create 3-byte array (NB zero-based)
        Dim abDigest(19) As Byte ' Create 20-byte array to receive digest
        
        ' Setup byte array with "abc"
        abData(0) = Asc("a")
        abData(1) = Asc("b")
        abData(2) = Asc("c")
        
        ' Compute SHA-1 hash digest
        nRet = SHA1_BytesHash(abDigest(0), abData(0), 3)
        
        ' Print resulting bytes in hex format
        Debug.Print nRet; cnvHexStrFromBytes(abDigest)

End Sub

Public Sub V_Test_SHA1_BytesHash2()
    Debug.Print "Testing SHA1_BytesHash ..."
        Dim nRet As Long
        Dim abData(2) As Byte   ' Create 3-byte array (NB zero-based)
        Dim abDigest(19) As Byte ' Create 20-byte array to receive digest
        Dim i As Integer
        
        ' Setup byte array with "abc"
        abData(0) = Asc("a")
        abData(1) = Asc("b")
        abData(2) = Asc("c")
        
        ' Compute SHA-1 hash digest of input
        nRet = SHA1_BytesHash(abDigest(0), abData(0), 3)
        
        ' Now carry out repeated hashes of the digest
        For i = 2 To 1000
            nRet = SHA1_BytesHash(abDigest(0), abDigest(0), 20)
        Next
       
        ' Print H(1000) in hex format
        Debug.Print cnvHexStrFromBytes(abDigest)

End Sub

Public Sub V_Test_SHA1_BytesHexHash()
    Debug.Print "Testing SHA1_BytesHexHash ..."
        Dim nRet As Long
        Dim abData(2) As Byte   ' Create 3-byte array (NB zero-based)
        ' Alternative way of making sure string is 40 chars long
        Dim strDigest As String * 40
    
        ' Setup byte array with "abc"
        abData(0) = Asc("a")
        abData(1) = Asc("b")
        abData(2) = Asc("c")
    
        nRet = SHA1_BytesHexHash(strDigest, abData(0), 3)
        Debug.Print nRet; strDigest

End Sub

Public Sub V_Test_SHA1_FileHexHash()
    Debug.Print "Testing SHA1_FileHexHash ..."
        Dim nRet As Long
        Dim strDigest As String
        Dim strFileName As String
    
        strFileName = "hello.txt"
        ' Set strDigest to be 40 chars
        strDigest = String(40, " ")
        ' Make sha1sum in text mode (treating CR-LF as single NL)
        nRet = SHA1_FileHexHash(strDigest, strFileName, "t")
        Debug.Print "t " & nRet; strDigest
        ' Do in binary mode (treating CR-LF as two binary bytes)
        nRet = SHA1_FileHexHash(strDigest, strFileName, "b")
        Debug.Print "b " & nRet; strDigest

End Sub

Public Sub V_Test_SHA1_Hmac()
    Debug.Print "Testing SHA1_Hmac ..."
        Dim nRet As Long
        Dim abData() As Byte
        Dim abKey() As Byte
        Dim i As Integer
        Dim nDataLen As Long, nKeyLen As Long
        Dim strDigest As String * 40
    
        ' Test No 1.
        ' Set key = 0x0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b
        ReDim abKey(15)
        For i = 0 To 15
            abKey(i) = &HB
        Next
        ' Convert string to byte array
        abData() = StrConv("Hi There", vbFromUnicode)
        nDataLen = UBound(abData) + 1
        ' Create HMAC digest
        nRet = SHA1_Hmac(strDigest, abData(0), nDataLen, abKey(0), 16)
        Debug.Print 1; nRet; strDigest
    
        ' Test No 2.
        abKey() = StrConv("Jefe", vbFromUnicode)
        nKeyLen = UBound(abKey) + 1
        abData() = StrConv("what do ya want for nothing?", vbFromUnicode)
        nDataLen = UBound(abData) + 1
        nRet = SHA1_Hmac(strDigest, abData(0), nDataLen, abKey(0), nKeyLen)
        Debug.Print 2; nRet; strDigest
    
        ' Test No 3.
        ReDim abKey(15)
        For i = 0 To 15
            abKey(i) = &HAA
        Next
        ReDim abData(49)
        For i = 0 To 49
            abData(i) = &HDD
        Next
        nRet = SHA1_Hmac(strDigest, abData(0), 50, abKey(0), 16)
        Debug.Print 3; nRet; strDigest

End Sub

Public Sub V_Test_SHA1_HmacHex()
    Debug.Print "Testing SHA1_HmacHex ..."
    'Example from Wei Dai's Crypto++ test vectors
    'fipstest.cpp - written and placed in the public domain by Wei Dai
    'From http://trolocsis.com/crypto++/fipstest_8cpp-source.html
    'MAC_KnownAnswerTest<HMAC<SHA> >(
    '"303132333435363738393a3b3c3d3e3f40414243",
    '"Sample #2",
    '"0922d3405faa3d194f82a45830737d5cc6c75d24");
    
        Dim nRet As Long
        Dim strDigest As String * 40
        Dim strMessage As String
        Dim sHexMsg As String
        Dim sCorrect As String
        
        sCorrect = "0922d3405faa3d194f82a45830737d5cc6c75d24"
        
        ' Convert data to hex format
        sHexMsg = cnvHexStrFromString("Sample #2")
        nRet = SHA1_HmacHex(strDigest, sHexMsg, "303132333435363738393a3b3c3d3e3f40414243")
        Debug.Print "Digest =" & strDigest
        Debug.Print "Correct=" & sCorrect
        Debug.Assert (strDigest = sCorrect)

End Sub

Public Sub V_Test_SHA1_Reset()
    Debug.Print "Testing SHA1_Reset ..."
        Dim nRet As Long
        Dim hContext As Long
    
        hContext = SHA1_Init()
        nRet = SHA1_Reset(hContext)

End Sub

Public Sub V_Test_SHA1_StringHexHash()
    Debug.Print "Testing SHA1_StringHexHash ..."
        Dim nRet As Long
        Dim strDigest As String
        ' Set strDigest to be 40 chars
        strDigest = String(40, " ")
        nRet = SHA1_StringHexHash(strDigest, "abc")
        Debug.Print strDigest
    
        nRet = SHA1_StringHexHash(strDigest, _
            "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq")
        Debug.Print strDigest

End Sub

Public Sub V_Test_SHA2_AddBytes()
    Debug.Print "Testing SHA2_AddBytes ..."
        Dim nRet As Long
        Dim strDigest As String
        Dim hContext As Long
        Dim abData(2) As Byte
    
        ' Set context handle
        hContext = SHA2_Init()
        ' Remember to check for an invalid handle
        If hContext = 0 Then
            MsgBox "Failed to set context"
            Exit Sub
        End If
    
        ' Set up a test array of bytes
        abData(0) = Asc("a")
        abData(1) = &H62    ' same as Asc("b")
        ' Add mixture of bytes and strings
        nRet = SHA2_AddBytes(hContext, abData(0), 2)
        nRet = SHA2_AddString(hContext, "c")
    
        ' Set strDigest to be 64 chars
        strDigest = String(64, " ")
        nRet = SHA2_HexDigest(strDigest, hContext)
        Debug.Print strDigest

End Sub

Public Sub V_Test_SHA2_AddString()
    Debug.Print "Testing SHA2_AddString ..."
        Dim nRet As Long
        Dim strDigest As String
        Dim hContext As Long
        Dim i As Long
        Dim sA1000 As String
    
        ' Set context handle
        hContext = SHA2_Init()
        If hContext = 0 Then
            MsgBox "Failed to set context"
            Exit Sub
        End If
    
        ' Create a string of 1000 'a's
        sA1000 = String(1000, "a")
    
        ' Add 1000 times => one million repetitions of "a"
        For i = 1 To 1000
            nRet = SHA2_AddString(hContext, sA1000)
        Next
    
        ' Set strDigest to be 64 chars - don't forget!!
        strDigest = String(64, " ")
        nRet = SHA2_HexDigest(strDigest, hContext)
        Debug.Print strDigest

End Sub

Public Sub V_Test_SHA2_BytesHash()
    Debug.Print "Testing SHA2_BytesHash ..."
        Dim nRet As Long
        Dim abData(2) As Byte   ' Create 3-byte array (NB zero-based)
        Dim abDigest(31) As Byte ' Create 32-byte array to receive digest
        
        ' Setup byte array with "abc"
        abData(0) = Asc("a")
        abData(1) = Asc("b")
        abData(2) = Asc("c")
        
        ' Compute SHA-256 hash digest
        nRet = SHA2_BytesHash(abDigest(0), abData(0), 3)
        
        ' Print resulting bytes in hex format
        Debug.Print nRet; cnvHexStrFromBytes(abDigest)

End Sub

Public Sub V_Test_SHA2_BytesHash2()
    Debug.Print "Testing SHA2_BytesHash ..."
        Dim nRet As Long
        Dim abData(2) As Byte   ' Create 3-byte array (NB zero-based)
        Dim abDigest(31) As Byte ' Create 32-byte array to receive digest
        Dim i As Integer
        
        ' Setup byte array with "abc"
        abData(0) = Asc("a")
        abData(1) = Asc("b")
        abData(2) = Asc("c")
        
        ' Compute SHA-256 hash digest of input
        nRet = SHA2_BytesHash(abDigest(0), abData(0), 3)
        
        ' Now carry out repeated hashes of the digest
        For i = 2 To 1000
            nRet = SHA2_BytesHash(abDigest(0), abDigest(0), 32)
        Next
       
        ' Print H(1000) in hex format
        Debug.Print cnvHexStrFromBytes(abDigest)

End Sub

Public Sub V_Test_SHA2_BytesHexHash()
    Debug.Print "Testing SHA2_BytesHexHash ..."
        Dim nRet As Long
        Dim abData(2) As Byte   ' Create 3-byte array (NB zero-based)
        ' Alternative way of making sure string is 64 chars long
        Dim strDigest As String * 64
    
        ' Setup byte array with "abc"
        abData(0) = Asc("a")
        abData(1) = Asc("b")
        abData(2) = Asc("c")
    
        nRet = SHA2_BytesHexHash(strDigest, abData(0), 3)
        Debug.Print nRet; strDigest

End Sub

Public Sub V_Test_SHA2_FileHexHash()
    Debug.Print "Testing SHA2_FileHexHash ..."
        Dim nRet As Long
        Dim strDigest As String
        Dim strFileName As String
    
        strFileName = "hello.txt"
        ' Set strDigest to be 64 chars
        strDigest = String(64, " ")
        ' Make sha1sum in text mode (treating CR-LF as single NL)
        nRet = SHA2_FileHexHash(strDigest, strFileName, "t")
        Debug.Print "t " & nRet; strDigest
        ' Do in binary mode (treating CR-LF as two binary bytes)
        nRet = SHA2_FileHexHash(strDigest, strFileName, "b")
        Debug.Print "b " & nRet; strDigest

End Sub

Public Sub V_Test_SHA2_Hmac()
    Debug.Print "Testing SHA2_Hmac ..."
        Dim nRet As Long
        Dim abData() As Byte
        Dim abKey() As Byte
        Dim i As Integer
        Dim nDataLen As Long, nKeyLen As Long
        Dim strDigest As String * 64
    
        ' Test No 1.
        ' Set key = 0x0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b
        ReDim abKey(15)
        For i = 0 To 15
            abKey(i) = &HB
        Next
        ' Convert string to byte array
        abData() = StrConv("Hi There", vbFromUnicode)
        nDataLen = UBound(abData) + 1
        ' Create HMAC digest
        nRet = SHA2_Hmac(strDigest, abData(0), nDataLen, abKey(0), 16)
        Debug.Print 1; nRet; strDigest
    
        ' Test No 2.
        abKey() = StrConv("Jefe", vbFromUnicode)
        nKeyLen = UBound(abKey) + 1
        abData() = StrConv("what do ya want for nothing?", vbFromUnicode)
        nDataLen = UBound(abData) + 1
        nRet = SHA2_Hmac(strDigest, abData(0), nDataLen, abKey(0), nKeyLen)
        Debug.Print 2; nRet; strDigest
    
        ' Test No 3.
        ReDim abKey(15)
        For i = 0 To 15
            abKey(i) = &HAA
        Next
        ReDim abData(49)
        For i = 0 To 49
            abData(i) = &HDD
        Next
        nRet = SHA2_Hmac(strDigest, abData(0), 50, abKey(0), 16)
        Debug.Print 3; nRet; strDigest

End Sub

Public Sub V_Test_SHA2_HmacHex()
    Debug.Print "Testing SHA2_HmacHex ..."
    'Example from Wei Dai's Crypto++ test vectors
    'fipstest.cpp - written and placed in the public domain by Wei Dai
    'From http://trolocsis.com/crypto++/fipstest_8cpp-source.html
    'MAC_KnownAnswerTest<HMAC<SHA256> >(
    '"303132333435363738393a3b3c3d3e3f40414243",
    '"abc",
    '"D28363F335B2DAE468793A38680DEA9F7FB8BE1DCEDA197CDB3B1CB59A9F6422");
    
        Dim nRet As Long
        Dim strDigest As String * 64
        Dim strMessage As String
        Dim sHexMsg As String
        Dim sCorrect As String
        
        sCorrect = "d28363f335b2dae468793a38680dea9f7fb8be1dceda197cdb3b1cb59a9f6422"
        
        ' Convert data to hex format
        sHexMsg = cnvHexStrFromString("abc")
        nRet = SHA2_HmacHex(strDigest, sHexMsg, "303132333435363738393a3b3c3d3e3f40414243")
        Debug.Print "Digest =" & strDigest
        Debug.Print "Correct=" & sCorrect
        Debug.Assert (strDigest = sCorrect)

End Sub

Public Sub V_Test_SHA2_Reset()
    Debug.Print "Testing SHA2_Reset ..."
        Dim nRet As Long
        Dim hContext As Long
    
        hContext = SHA2_Init()
        nRet = SHA2_Reset(hContext)

End Sub

Public Sub V_Test_SHA2_StringHexHash()
    Debug.Print "Testing SHA2_StringHexHash ..."
        Dim nRet As Long
        Dim strDigest As String
        ' Set strDigest to be 64 chars
        strDigest = String(64, " ")
        nRet = SHA2_StringHexHash(strDigest, "abc")
        Debug.Print strDigest
    
        nRet = SHA2_StringHexHash(strDigest, _
            "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq")
        Debug.Print strDigest

End Sub

Public Sub V_Test_SHA3_AddBytes()
    Debug.Print "Testing SHA3_AddBytes ..."
    Dim nRet As Long
    Dim nBytes As Long
    Dim strDigest As String
    Dim hContext As Long
    Dim abData(1) As Byte
    
    ' Set context handle
    hContext = SHA3_Init(256)
    ' Check for an invalid handle
    If hContext = 0 Then
      MsgBox "Failed to set context"
      Exit Sub
    End If
    
    ' Set up a test array of bytes
    abData(0) = Asc("a")
    abData(1) = &H62    ' same as Asc("b")
    ' Add mixture of bytes and strings to pass "abc"
    nRet = SHA3_AddBytes(hContext, abData(0), 2)
    nRet = SHA3_AddString(hContext, "c")
    
    ' Get required length of output string (NB 2 times number of bytes)
    nBytes = SHA3_LengthInBytes(hContext)
    strDigest = String(nBytes * 2, " ")
    nRet = SHA3_HexDigest(strDigest, Len(strDigest), hContext)
    Debug.Print strDigest

End Sub

Public Sub V_Test_SHA3_AddString()
    Debug.Print "Testing SHA3_AddString ..."
    Dim nRet As Long
    Dim nBytes As Long
    Dim strDigest As String
    Dim hContext As Long
    Dim i As Long
    Dim sA1000 As String
    
    ' Set context handle
    hContext = SHA3_Init(224)
    If hContext = 0 Then
      MsgBox "Failed to set context"
      Exit Sub
    End If
    
    ' Create a string of 1000 'a's
    sA1000 = String(1000, "a")
    
    ' Add 1000 times => one million repetitions of "a"
    For i = 1 To 1000
      nRet = SHA3_AddString(hContext, sA1000)
    Next
    
    ' Get required length of output string (NB 2 times number of bytes)
    nBytes = SHA3_LengthInBytes(hContext)
    strDigest = String(nBytes * 2, " ")
    nRet = SHA3_HexDigest(strDigest, Len(strDigest), hContext)
    Debug.Print strDigest

End Sub

Public Sub V_Test_SHA3_Reset()
    Debug.Print "Testing SHA3_Reset ..."
    Dim nRet As Long
    Dim nLen As Long
    Dim hContext As Long
    
    hContext = SHA3_Init(384)
    Debug.Print "SHA3_Init returns 0x" & Hex(hContext)
    Debug.Assert hContext <> 0
    nLen = SHA3_LengthInBytes(hContext)
    Debug.Print "SHA3_LengthInBytes=" & nLen
    
    ' Destroy the context
    nRet = SHA3_Reset(hContext)
    Debug.Print "SHA3_Reset returns " & nRet
    
    ' Now we have an invalid context handle
    nLen = SHA3_LengthInBytes(hContext)
    Debug.Print "SHA3_LengthInBytes returns " & nLen
    Debug.Print apiErrorLookup(nLen)

End Sub

Public Sub V_Test_TDEA_B64Mode()
    Debug.Print "Testing TDEA_B64Mode ..."
    Dim nRet As Long
    Dim strOutput As String
    Dim strInput As String
    Dim strKey As String
    Dim strIV As String
    Dim bEncrypt As Boolean
    Dim sCorrect As String
    
    ' Key is 0x737C791F25EAD0E04629254352F7DC6291E5CB26917ADA32
    strKey = "c3x5HyXq0OBGKSVDUvfcYpHlyyaRetoy"
    ' IV is 0xB36B6BFB6231084E
    strIV = "s2tr+2IxCE4="
    ' 0x5468697320736F6D652073616D706520636F6E74656E742E0808080808080808
    '  "T h i s _ s o m e _ s a m p e _ c o n t e n t ." (padding 8 x 08)
    strInput = "VGhpcyBzb21lIHNhbXBlIGNvbnRlbnQuCAgICAgICAg="
    sCorrect = "12/RF4+9AvhCMfXB0qL3SkFZSClk9nUkglQiPa+a+OQ="
    
    ' Set strOutput to be same length as strInput
    strOutput = String(Len(strInput), " ")
    
    Debug.Print "KY=" & strKey
    Debug.Print "IV=" & strIV
    Debug.Print "PT=" & strInput
    nRet = TDEA_B64Mode(strOutput, strInput, strKey, ENCRYPT, "CBC", strIV)
    Debug.Print "CT=" & strOutput; nRet
    Debug.Print "OK=" & sCorrect
    
    strInput = strOutput
    nRet = TDEA_B64Mode(strOutput, strInput, strKey, DECRYPT, "CBC", strIV)
    Debug.Print "P'=" & strOutput; nRet

End Sub

Public Sub V_Test_TDEA_Bytes()
    Debug.Print "Testing TDEA_Bytes ..."
        Dim nRet As Long
        Dim strInput As String
        Dim strKey As String
        Dim sCorrect As String
        Dim abKey() As Byte
        Dim abOutput() As Byte
        Dim abData() As Byte
        Dim nDataLen As Long
        
        ' Define test vectors in hex
        strKey = "0123456789abcdeffedcba987654321089abcdef01234567"
        strInput = "0123456789abcde70123456789abcde7"
        sCorrect = "de0b7c06ae5e0ed5de0b7c06ae5e0ed5"
        
        ' Convert to byte arrays and compute lengths
        abKey = cnvBytesFromHexStr(strKey)
        abData = cnvBytesFromHexStr(strInput)
        nDataLen = Len(strInput) \ 2
        
        ' Dimension array for output
        ReDim abOutput(nDataLen - 1)
        
        Debug.Print "KY=" & cnvHexStrFromBytes(abKey)
        Debug.Print "PT=" & cnvHexStrFromBytes(abData)
        ' Encrypt in one-off process
        nRet = TDEA_Bytes(abOutput(0), abData(0), nDataLen, abKey(0), ENCRYPT)
        Debug.Print "CT=" & cnvHexStrFromBytes(abOutput), nRet
        Debug.Print "OK=" & sCorrect
        Debug.Assert (sCorrect = cnvHexStrFromBytes(abOutput))
        
        ' Now decrypt back
        nRet = TDEA_Bytes(abData(0), abOutput(0), nDataLen, abKey(0), DECRYPT)
        Debug.Print "P'=" & cnvHexStrFromBytes(abData), nRet
        Debug.Assert (strInput = cnvHexStrFromBytes(abData))

End Sub

Public Sub V_Test_TDEA_BytesMode()
    Debug.Print "Testing TDEA_BytesMode ..."
    Dim nRet As Long
    Dim strOutput As String
    Dim strInput As String
    Dim strKey As String
    Dim strHexIV As String
    Dim sCorrect As String
    Dim nDataLen As Long
    Dim abKey() As Byte
    Dim abOutput() As Byte
    Dim abData() As Byte
    Dim abInitV() As Byte
    
    strKey = "0123456789abcdeffedcba987654321089abcdef01234567"
    strHexIV = "1234567890abcdef"
    strInput = "Now is the time for all "
    sCorrect = "204011f986e35647199e47af391620c5bb9a5bcfc86db0bb"
    
    ' Convert to byte arrays and compute lengths
    abKey = cnvBytesFromHexStr(strKey)
    abInitV = cnvBytesFromHexStr(strHexIV)
    abData = StrConv(strInput, vbFromUnicode)
    nDataLen = Len(strInput)
    
    ' Dimension array for output
    ReDim abOutput(nDataLen - 1)
    
    Debug.Print "KY=" & cnvHexStrFromBytes(abKey)
    Debug.Print "IV=" & cnvHexStrFromBytes(abInitV)
    Debug.Print "PT=" & cnvHexStrFromBytes(abData)
    
    ' Encrypt in one-off process
    nRet = TDEA_BytesMode(abOutput(0), abData(0), nDataLen, _
        abKey(0), True, "CBC", abInitV(0))
    Debug.Print "CT=" & cnvHexStrFromBytes(abOutput)
    Debug.Print "OK=" & sCorrect
    Debug.Assert (sCorrect = cnvHexStrFromBytes(abOutput))
    
    ' Now decrypt back
    nRet = TDEA_BytesMode(abData(0), abOutput(0), nDataLen, _
        abKey(0), DECRYPT, "CBC", abInitV(0))
    strOutput = StrConv(abData(), vbUnicode)
    Debug.Print "P'=" & "[" & strOutput & "]"
    Debug.Assert (strOutput = strInput)

End Sub

Public Sub V_Test_TDEA_File()
    Debug.Print "Testing TDEA_File ..."
        Const MY_PATH As String = ""
        Dim abKey() 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}
        abKey = cnvBytesFromHexStr("fedcba9876543210fedcba9876543210fedcba9876543210")
    
        ' Encrypt plaintext file to ciphertext
        ' Output file = 16-byte ciphertext file hello.enc
        nRet = TDEA_File(strFileOut, strFileIn, abKey(0), ENCRYPT, "ECB", 0)
        Debug.Print nRet
    
        ' Now decrypt it
        nRet = TDEA_File(strFileChk, strFileOut, abKey(0), DECRYPT, "ECB", 0)
        Debug.Print nRet

End Sub

Public Sub V_Test_TDEA_FileExt()
    Debug.Print "Testing TDEA_FileExt ..."
    Dim abKey() As Byte
    Dim abIV() As Byte
    Dim strFilePlain As String
    Dim strFileCipher As String
    Dim strFileCheck As String
    Dim strFileChk1 As String
    Dim nRet As Long
    
    ' Input file is exactly 19 bytes long
    strFilePlain = "nowis19.txt"
    strFileCipher = "nowis19.tdea.enc.dat"
    strFileCheck = "nowis19.tdea.chk.txt"
    strFileChk1 = "nowis19.tdea.chk1.txt"
    
    ' Create the key and IV as arrays of bytes
    ' This creates an array of 24 bytes {&H01, &H23, ... &H67}
    abKey = cnvBytesFromHexStr("0123456789ABCDEFFEDCBA987654321089ABCDEF01234567")
    ' This creates an array of 8 bytes {&H12, &H34, ... &HEF}
    abIV = cnvBytesFromHexStr("1234567890ABCDEF ")
    
    ' Encrypt plaintext file to ciphertext with embedded IV at beginning
    ' Output file = 32-byte ciphertext file .enc.dat
    nRet = TDEA_FileExt(strFileCipher, strFilePlain, abKey(0), ENCRYPT, "CBC", abIV(0), API_IV_PREFIX)
    Debug.Print "TDEA_FileExt(ENCRYPT) returns " & nRet
    Debug.Print "Output file '" & strFileCipher & "' is " & FileLen(strFileCipher) & " bytes"
    
    ' Now decrypt it back to original plaintext - this file should be 19 bytes long
    nRet = TDEA_FileExt(strFileCheck, strFileCipher, abKey(0), DECRYPT, "CBC", abIV(0), API_IV_PREFIX)
    Debug.Print "TDEA_FileExt(DECRYPT) returns " & nRet
    Debug.Print "Output file '" & strFileCheck & "' is " & FileLen(strFileCheck) & " bytes"
    
    ' Alternatively, decrypt and leave padding bytes in place - this file should be 24 bytes long
    nRet = TDEA_FileExt(strFileChk1, strFileCipher, abKey(0), DECRYPT, "CBC", abIV(0), API_IV_PREFIX + API_PAD_LEAVE)
    Debug.Print "TDEA_FileExt(DECRYPT, API_PAD_LEAVE) returns " & nRet
    Debug.Print "Output file '" & strFileChk1 & "' is " & FileLen(strFileChk1) & " bytes"

End Sub

Public Sub V_Test_TDEA_FileHex()
    Debug.Print "Testing TDEA_FileHex ..."
        Dim nRet As Long
    
        nRet = TDEA_FileHex("bigfile.cbc", "bigfile.dat", _
            "fedcba9876543210fedcba9876543210fedcba9876543210", _
            ENCRYPT, "CBC", "0123456789abcdef")
        Debug.Print nRet
    
        ' and decrypt it as a check
        nRet = TDEA_FileHex("bigfile.chk", "bigfile.cbc", _
            "fedcba9876543210fedcba9876543210fedcba9876543210", _
            DECRYPT, "CBC", "0123456789abcdef")
        Debug.Print nRet

End Sub

Public Sub V_Test_TDEA_Hex()
    Debug.Print "Testing TDEA_Hex ..."
        Dim nRet As Long
        Dim strOutput As String
        Dim strInput As String
        Dim strKey As String
        Dim bEncrypt As Boolean
        Dim sCorrect As String
    
        strInput = "8000000000000000"
        strKey = "010101010101010101010101010101010101010101010101"
        sCorrect = "95F8A5E5DD31D900"
        ' Set strOutput to be same length as strInput
        strOutput = String(Len(strInput), " ")
    
        Debug.Print "KY=" & strKey
        Debug.Print "PT=" & strInput
        ' Encrypt
        nRet = TDEA_Hex(strOutput, strInput, strKey, ENCRYPT)
        Debug.Print "CT=" & strOutput, "Return value=" & nRet
        Debug.Print "OK=" & sCorrect
    
        ' Decrypt back
        strInput = strOutput
        nRet = TDEA_Hex(strOutput, strInput, strKey, DECRYPT)
        Debug.Print "P'=" & strOutput & "Return value=" & nRet

End Sub

Public Sub V_Test_TDEA_HexMode()
    Debug.Print "Testing TDEA_HexMode ..."
        Dim nRet As Long
        Dim strOutput As String
        Dim strInput As String
        Dim strKey As String
        Dim strIV As String
        Dim bEncrypt As Boolean
        Dim sCorrect As String
    
        strInput = "5468697320736F6D652073616D706520636F6E74656E742E0808080808080808"
        strKey = "737C791F25EAD0E04629254352F7DC6291E5CB26917ADA32"
        strIV = "B36B6BFB6231084E"
        sCorrect = "d76fd1178fbd02f84231f5c1d2a2f74a4159482964f675248254223daf9af8e4"
        ' Set strOutput to be same length as strInput
        strOutput = String(Len(strInput), " ")
    
        Debug.Print "KY=" & strKey
        Debug.Print "PT=" & strInput
        nRet = TDEA_HexMode(strOutput, strInput, strKey, True, "CBC", strIV)
        Debug.Print "CT=" & strOutput; nRet
        Debug.Print "OK=" & sCorrect
    
        strInput = strOutput
        nRet = TDEA_HexMode(strOutput, strInput, strKey, DECRYPT, "CBC", strIV)
        Debug.Print "P'=" & strOutput; nRet

End Sub

Public Sub V_Test_TDEA_Update()
    Debug.Print "Testing TDEA_Update ..."
        Dim nRet As Long
        Dim hContext As Long
        Dim sCorrect As String
        Dim j As Integer
        Dim abKey() As Byte
        Dim abInitV() As Byte
        Dim aBlock() As Byte
        Dim aNext() As Byte
        Dim aLast() As Byte
    
        aBlock() = StrConv("Now is t", vbFromUnicode)
        abKey = cnvBytesFromHexStr( _
            "0123456789abcdef23456789abcdef01456789abcdef0123")
        abInitV = cnvBytesFromHexStr("1234567890abcdef")
        sCorrect = "cb191f85d1ed8439"
    
        Debug.Print "TDEA Monte Carlo TCBC Mode Encrypt:"
        Debug.Print "KY=" & cnvHexStrFromBytes(abKey)
        Debug.Print "IV=" & cnvHexStrFromBytes(abInitV)
        Debug.Print "PT=" & cnvHexStrFromBytes(aBlock)
    
        hContext = TDEA_Init(abKey(0), True, "CBC", abInitV(0))
        If hContext = 0 Then
            nRet = TDEA_InitError()
            Debug.Print "TDEA_Init Failed: " & apiErrorLookup(nRet)
            Exit Sub
        End If
        ' Do 10,000 times
        aNext() = aBlock()
        For j = 0 To 9999
            aBlock() = aNext()
            nRet = TDEA_Update(hContext, aBlock(0), 8)
            If j = 0 Then
                aNext() = abInitV()
            Else
                aNext() = aLast()
            End If
            aLast() = aBlock()
        Next
        Debug.Print "CT=" & cnvHexStrFromBytes(aBlock)
        Debug.Print "OK=" & sCorrect
        nRet = TDEA_Final(hContext)
        
        Debug.Assert (sCorrect = cnvHexStrFromBytes(aBlock))

End Sub

Public Sub V_Test_TDEA_UpdateHex()
    Debug.Print "Testing TDEA_UpdateHex ..."
        Dim nRet As Long
        Dim hContext As Long
        Dim sBlock As String
        Dim strKey As String
        Dim strIV As String
        Dim sNext As String
        Dim sLast As String
        Dim sCorrect As String
        Dim j As Integer
    
        sBlock = "4e6f772069732074"
        strKey = "0123456789abcdef" & _
                "23456789abcdef01" & _
                "456789abcdef0123"
        strIV = "1234567890abcdef"
        sCorrect = "cb191f85d1ed8439"
    
        Debug.Print "TDEA Monte Carlo TCBC Mode Encrypt:"
        Debug.Print "KY=" & strKey
        Debug.Print "IV=" & strIV
        Debug.Print "PT=" & sBlock
    
        hContext = TDEA_InitHex(strKey, True, "CBC", strIV)
        If hContext = 0 Then
            Exit Sub
        End If
        ' Do 10,000 times
        sNext = sBlock
        For j = 0 To 9999
            sBlock = sNext
            nRet = TDEA_UpdateHex(hContext, sBlock)
            If j = 0 Then
                sNext = strIV
            Else
                sNext = sLast
            End If
            sLast = sBlock
        Next
        Debug.Print "CT=" & sBlock
        Debug.Print "OK=" & sCorrect
        nRet = TDEA_Final(hContext)

End Sub

Public Sub V_Test_WIPE_Data()
    Debug.Print "Testing WIPE_Data ..."
    Dim abData(3) As Byte
    Dim nLen As Long
    Dim nRet As Long
    ' Set up data in byte array
    abData(0) = &HDE
    abData(1) = &HAD
    abData(2) = &HBE
    abData(3) = &HEF
    Debug.Print "Before WIPE_Data: " & "[" & cnvHexStrFromBytes(abData) & "]"
    nLen = UBound(abData) - LBound(abData) + 1
    nRet = WIPE_Data(abData(0), nLen)
    Debug.Print "After WIPE_Data:  " & "[" & cnvHexStrFromBytes(abData) & "]"

End Sub

Public Sub V_Test_WIPE_Data2()
    Debug.Print "Testing WIPE_Data ..."
    Dim strData As String
    Dim nRet As Long
    strData = "my deepest secrets"
    Debug.Print "Before WIPE_String: " & "[" & strData & "]"
    nRet = WIPE_String(strData, Len(strData))
    ' Set to empty as well...
    strData = ""
    Debug.Print "After WIPE_String:  " & "[" & strData & "]"

End Sub

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

End Sub

Public Sub V_Test_ZLIB_Deflate()
    Debug.Print "Testing ZLIB_Deflate ..."
    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 = ZLIB_Deflate(0, 0, abPlain(0), nUncompLen)
    Debug.Print "COMPR-LEN=" & nCompLen
    ReDim abCompressed(nCompLen - 1)
    ' Now compress plaintext
    Call ZLIB_Deflate(abCompressed(0), nCompLen, abPlain(0), nUncompLen)
    ' Display compressed data in hex
    Debug.Print "COMPR-DATA=" & cnvHexStrFromBytes(abCompressed)
    
    ' DECOMPRESSSION (inflation)
    
    ' Uncompress the compressed data
    ' New in [v5.3]: we can find the uncompressed length from compressed data
    nUncompLen = ZLIB_Inflate(vbNull, 0, abCompressed(0), nCompLen)
    Debug.Print "Uncompressed length = " & nUncompLen
    Debug.Assert (nUncompLen > 0)
    ReDim abPlain(nUncompLen - 1)
    nRet = ZLIB_Inflate(abPlain(0), nUncompLen, abCompressed(0), nCompLen)
    
    ' Convert back to a string
    strBack = StrConv(abPlain, vbUnicode)
    Debug.Print strBack

End Sub

Public Sub V_DoAllTests()
    Call V_Test_AEAD_Decrypt
    Call V_Test_AEAD_Encrypt
    Call V_Test_AEAD_Encrypt2
    Call V_Test_AES128_B64Mode
    Call V_Test_AES128_Bytes
    Call V_Test_AES128_BytesMode
    Call V_Test_AES128_File
    Call V_Test_AES128_FileExt
    Call V_Test_AES128_FileHex
    Call V_Test_AES128_Hex
    Call V_Test_AES128_HexMode
    Call V_Test_AES128_InitError
    Call V_Test_AES128_Update
    Call V_Test_AES128_UpdateHex
    Call V_Test_AES192_B64Mode
    Call V_Test_AES192_Bytes
    Call V_Test_AES192_BytesMode
    Call V_Test_AES192_File
    Call V_Test_AES192_FileExt
    Call V_Test_AES192_FileHex
    Call V_Test_AES192_Hex
    Call V_Test_AES192_HexMode
    Call V_Test_AES192_InitError
    Call V_Test_AES192_Update
    Call V_Test_AES192_UpdateHex
    Call V_Test_AES256_B64Mode
    Call V_Test_AES256_Bytes
    Call V_Test_AES256_BytesMode
    Call V_Test_AES256_File
    Call V_Test_AES256_FileExt
    Call V_Test_AES256_FileHex
    Call V_Test_AES256_Hex
    Call V_Test_AES256_HexMode
    Call V_Test_AES256_InitError
    Call V_Test_AES256_Update
    Call V_Test_AES256_UpdateHex
    Call V_Test_API_CompileTime
    Call V_Test_API_ErrorCode
    Call V_Test_API_ErrorLookup
    Call V_Test_API_ErrorLookup2
    Call V_Test_API_LicenceType
    Call V_Test_API_PowerUpTests
    Call V_Test_API_Version
    Call V_Test_BLF_B64Mode
    Call V_Test_BLF_Bytes
    Call V_Test_BLF_BytesMode
    Call V_Test_BLF_File
    Call V_Test_BLF_FileExt
    Call V_Test_BLF_FileHex
    Call V_Test_BLF_Hex
    Call V_Test_BLF_HexMode
    Call V_Test_BLF_Update
    Call V_Test_BLF_UpdateHex
    Call V_Test_CIPHER_DecryptBytes2
    Call V_Test_CIPHER_EncryptBytes2
    Call V_Test_CIPHER_FileEncrypt
    Call V_Test_CIPHER_KeyWrap
    Call V_Test_CIPHER_KeyUnwrap
    Call V_Test_CIPHER_StreamBytes
    Call V_Test_CIPHER_StreamBytes2
    Call V_Test_CIPHER_StreamFile
    Call V_Test_CIPHER_StreamHex
    Call V_Test_CIPHER_StreamInit
    Call V_Test_CRC_Bytes
    Call V_Test_CRC_File
    Call V_Test_CRC_String
    Call V_Test_DES_B64Mode
    Call V_Test_DES_Bytes
    Call V_Test_DES_BytesMode
    Call V_Test_DES_CheckKey
    Call V_Test_DES_CheckKeyHex
    Call V_Test_DES_File
    Call V_Test_DES_FileExt
    Call V_Test_DES_FileHex
    Call V_Test_DES_Hex
    Call V_Test_DES_HexMode
    Call V_Test_DES_Update
    Call V_Test_DES_UpdateHex
    Call V_Test_GCM_Encrypt
    Call V_Test_GCM_Encrypt2
    Call V_Test_GCM_InitKey
    Call V_Test_HASH_Bytes
    Call V_Test_HASH_File
    Call V_Test_HASH_HexFromBits
    Call V_Test_HASH_HexFromBits2
    Call V_Test_HASH_HexFromBytes
    Call V_Test_HASH_HexFromBytes2
    Call V_Test_HASH_HexFromFile
    Call V_Test_HASH_HexFromHex
    Call V_Test_MAC_Bytes
    Call V_Test_MAC_HexFromBytes
    Call V_Test_MAC_HexFromHex
    Call V_Test_MAC_HexFromHex2
    Call V_Test_MAC_HexFromHex3
    Call V_Test_MD5_AddBytes
    Call V_Test_MD5_AddString
    Call V_Test_MD5_BytesHash
    Call V_Test_MD5_BytesHash2
    Call V_Test_MD5_BytesHexHash
    Call V_Test_MD5_FileHexHash
    Call V_Test_MD5_Hmac
    Call V_Test_MD5_HmacHex
    Call V_Test_MD5_Reset
    Call V_Test_MD5_StringHexHash
    Call V_Test_PAD_BytesBlock
    Call V_Test_PAD_HexBlock
    Call V_Test_PAD_HexBlock2
    Call V_Test_PAD_UnpadHex
    Call V_Test_PBE_Kdf2
    Call V_Test_PBE_Kdf22
    Call V_Test_PBE_Kdf2Hex
    Call V_Test_PBE_Scrypt
    Call V_Test_PBE_ScryptHex
    Call V_Test_PC1_Bytes
    Call V_Test_PC1_File
    Call V_Test_PC1_Hex
    Call V_Test_RNG_Initialize
    Call V_Test_RNG_KeyBytes
    Call V_Test_RNG_KeyHex
    Call V_Test_RNG_NonceData
    Call V_Test_RNG_NonceDataHex
    Call V_Test_RNG_Number
    Call V_Test_RNG_Test
    Call V_Test_RNG_TestDRBGVS
    Call V_Test_SHA1_AddBytes
    Call V_Test_SHA1_AddString
    Call V_Test_SHA1_BytesHash
    Call V_Test_SHA1_BytesHash2
    Call V_Test_SHA1_BytesHexHash
    Call V_Test_SHA1_FileHexHash
    Call V_Test_SHA1_Hmac
    Call V_Test_SHA1_HmacHex
    Call V_Test_SHA1_Reset
    Call V_Test_SHA1_StringHexHash
    Call V_Test_SHA2_AddBytes
    Call V_Test_SHA2_AddString
    Call V_Test_SHA2_BytesHash
    Call V_Test_SHA2_BytesHash2
    Call V_Test_SHA2_BytesHexHash
    Call V_Test_SHA2_FileHexHash
    Call V_Test_SHA2_Hmac
    Call V_Test_SHA2_HmacHex
    Call V_Test_SHA2_Reset
    Call V_Test_SHA2_StringHexHash
    Call V_Test_SHA3_AddBytes
    Call V_Test_SHA3_AddString
    Call V_Test_SHA3_Reset
    Call V_Test_TDEA_B64Mode
    Call V_Test_TDEA_Bytes
    Call V_Test_TDEA_BytesMode
    Call V_Test_TDEA_File
    Call V_Test_TDEA_FileExt
    Call V_Test_TDEA_FileHex
    Call V_Test_TDEA_Hex
    Call V_Test_TDEA_HexMode
    Call V_Test_TDEA_Update
    Call V_Test_TDEA_UpdateHex
    Call V_Test_WIPE_Data
    Call V_Test_WIPE_Data2
    Call V_Test_WIPE_File
    Call V_Test_ZLIB_Deflate
Debug.Print "ALL DONE."
End Sub