CryptoSys Home > API > Encrypting files using CryptoSys API

Encrypting files using CryptoSys API


Question:

Looking at using your package in a VB6 application. I want to be able to encrypt using AES256 files which are typically about 8K in size. I then need to load this file in another application and decrypt it into an internal array.

Answer:

Here is one suggested solution. It assumes the VB6 module basCryptoSys.bas is included in your project.

' $Id: basTestFileEncrypt.bas $

Public Sub TestFileEncrypt()
    Dim abKey() As Byte
    Dim abIV() As Byte
    Dim strFilePlain As String
    Dim strFileCipher As String
    Dim nRet As Long
    Dim abData() As Byte
    Dim abResult() As Byte
    Dim nLen As Long
    Dim nLen1 As Long
    Dim i As Integer
    Dim strData As String

    ' File names
    strFilePlain = "sz8192.txt"     ' 8k times letter 'a'
    strFileCipher = "sz8192.enc.dat"

    ' Fixed "secret" key of exactly 256 bits (this must be a byte array 32 bytes long)
    abKey = cnvBytesFromHexStr("56e47a38c5598974bc46903dba29034906a9214036b8a15b512e03d534120006")
    
    ' ***************************
    ' ENCRYPTION OF FILE DIRECTLY
    ' ***************************
    ' Random IV each time of exactly 16 bytes/128 bits
    ReDim abIV(API_BLK_AES_BYTES - 1)
    Call RNG_NonceData(abIV(0), API_BLK_AES_BYTES)
    Debug.Print "IV=" & cnvHexStrFromBytes(abIV)

    ' Encrypt plaintext file to ciphertext with embedded IV at beginning
    ' Output file = 32-byte ciphertext file .enc.dat
    nRet = AES256_FileExt(strFileCipher, strFilePlain, abKey(0), ENCRYPT, "CBC", abIV(0), API_IV_PREFIX)
    Debug.Print "AES256_FileExt(ENCRYPT) returns " & nRet & " (expecting 0)"
    If (nRet <> 0) Then
        Debug.Print "ERROR: " & apiErrorLookup(nRet)
        Exit Sub
    End If
    Debug.Print "Input file  '" & strFilePlain & "' is " & FileLen(strFilePlain) & " bytes"
    Debug.Print "Output file '" & strFileCipher & "' is " & FileLen(strFileCipher) & " bytes"
    
    ' File structure for N encypted bytes:
    ' +---------+-------------------+
    ' | IV (16) | CIPHERTEXT (N)    |
    ' +---------+-------------------+
    
    ' ********************
    ' DECRYPTION IN MEMORY
    ' ********************
    ' Read in file to memory, then parse the IV, decrypt the remainder, and strip the padding
    abData = ReadFileIntoBytes(strFileCipher)
    nLen = ByteArrayLength(abData)
    Debug.Print "Input data is " & nLen & " bytes long"
    ' Copy the first 16 bytes into IV byte array
    ReDim abIV(API_BLK_AES_BYTES - 1)
    For i = 0 To API_BLK_AES_BYTES - 1
        abIV(i) = abData(i)
    Next
    Debug.Print "Parsed IV=" & cnvHexStrFromBytes(abIV)
    nLen1 = nLen - API_BLK_AES_BYTES    ' Length of ciphertext
    'Decrypt the byte array, starting at offset 16, expecting nLen1 bytes
    ReDim abResult(nLen1 - 1)
    nRet = AES256_BytesMode(abResult(0), abData(API_BLK_AES_BYTES), nLen1, abKey(0), DECRYPT, "CBC", abIV(0))
    Debug.Print "AES256_BytesMode(DECRYPT) returns " & nRet & " (expecting 0)"
    ' Strip the padding
    nRet = PAD_UnpadBytes(abResult(0), nLen1, abResult(0), nLen1, API_BLK_AES_BYTES, 0)
    If (nRet < 0) Then
        Debug.Print "ERROR: decryption error"
        Exit Sub
    End If
    ReDim Preserve abResult(nRet - 1)
    Debug.Print "Final result is " & ByteArrayLength(abResult) & " bytes"
    
    ' Convert the bytes into a string (assuming the plaintext was printable text)
    strData = StrConv(abResult, vbUnicode)
    ' Display the text result
    Debug.Print "RESULT=" & Left(strData, 15) & "..." & Right(strData, 15)

End Sub

Private Function ReadFileIntoBytes(sFilePath As String) As Variant
' Reads file (if it exists) into an array of bytes.
    Dim abData() As Byte
    Dim hFile As Integer
    
    ' Set default return value that won't cause a run-time error
    ReadFileIntoBytes = StrConv("", vbFromUnicode)
    ' Check if file exists
    If Len(Dir(sFilePath)) = 0 Then
        Exit Function
    End If
    hFile = FreeFile
    Open sFilePath For Binary Access Read As #hFile
    abData = InputB(LOF(hFile), #hFile)
    Close #hFile
    ReadFileIntoBytes = abData
    
End Function

Private Function ByteArrayLength(abData() As Byte) As Long
    On Error Resume Next    ' To catch uninitialized array
    ByteArrayLength = UBound(abData) - LBound(abData) + 1
End Function

Output

IV=0D05DCC55F4DA88CA82CECC4AD911886
AES256_FileExt(ENCRYPT) returns 0 (expecting 0)
Input file  'sz8192.txt' is 8192 bytes
Output file 'sz8192.enc.dat' is 8224 bytes
Input data is 8224 bytes long
Parsed IV=0D05DCC55F4DA88CA82CECC4AD911886
AES256_BytesMode(DECRYPT) returns 0 (expecting 0)
Final result is 8192 bytes
RESULT=aaaaaaaaaaaaaaa...aaaaaaaaaaaaaaa

Download

Source and data file (zipped).

Remarks

The input in this case is a text file consisting of exactly 8192 ASCII letter 'a' characters (included in the download). The AES256_FileExt() function uses the API_IV_PREFIX option to prepend the 16-byte initialization vector (IV) to the beginning of the file. You should always generate a new random value each time.

The AES256_FileExt() function automatically adds the correct padding. When we decrypt in memory, we need explicitly to strip this padding using the PAD_UnpadBytes function after decrypting. This can also detect some decryption errors, say, if you use the wrong key.

Most parameters are required in byte arrays. These are awkward to handle in VB6. See our page Byte Arrays in VB6 Visual Basic for some help.

Contact

For more information or to comment on this page, please send us a message.

This page first published 4 July 2014. Last updated for HTML5 16 June 2020.