Share My Creation One-Time Pad Encryption / Decryption of file too big to store in memory

I need to be able to encrypt a database file for storage in the clear on the internet. So I made the code below to encrypt and decrypt it using a one-time pad encryption.
The file will grow to be too big for memory to hold it so the code reads the plaintext 1 megabyte at a time, encrypts each byte and saves it one megabyte at a time. My previous code did everything one byte at a time and hammered the hard drive as a result. This is now much faster and much easier on the hard drive.

Here is the code to do so:

One-Time Pad Encrypt/Decrypt:
'==== Process Globals ====
Sub Process_Globals
    ' No global variables are needed.
    Dim xui As XUI
End Sub

Sub AppStart(Form1 As Form, Args() As String)
    Form1.Title = "One-Time Pad Addition Mod Encryption Demo"
    Form1.Show

    ' Define file names.
    Dim plainTextFile As String = "paypal_transactions.db"               ' Input file to be encrypted.
    Dim otpFile As String = "random.bin" ' OTP file; must be at least as big as the plaintext.  For perfect security, it needs to be truly random numbers.
    Dim encryptedFile As String = "paypal_transactions Encrypted.db"    ' Output file for encrypted data.
    Dim decryptedFile As String = "paypal_transactions Recovered.db"    ' Output file for decrypted data.

    ' Check that OTP file is large enough.
    Dim plainFileSize As Long = File.Size("D:\Downloads", plainTextFile)
    Dim otpFileSize As Long = File.Size("D:\Downloads", otpFile)
    If otpFileSize < plainFileSize Then
        xui.MsgboxAsync("Error: One-Time Pad file (" & otpFileSize & " bytes) is smaller than the plaintext file (" & plainFileSize & " bytes).", "PEBKAC Error")
        ExitApplication
    End If

    ' Perform encryption.
    EncryptFile(plainTextFile, otpFile, encryptedFile)
    Log("Encryption completed.")

    ' Perform decryption.
    DecryptFile(encryptedFile, otpFile, decryptedFile)
    Log("Decryption completed.")

    Form1.Close
End Sub

'----------------------------------------------------------------
' Encrypts a file using addition modulo 256.
' Reads the plaintext and OTP files in 1 MB blocks, encrypts each block,
' and writes the resulting encrypted data in 1 MB blocks.
Sub EncryptFile(inFile As String, otpFile As String, outFile As String)
    Dim inRAF As RandomAccessFile
    inRAF.Initialize("D:\Downloads", inFile, True)
    
    Dim otpRAF As RandomAccessFile
    otpRAF.Initialize("D:\Downloads", otpFile, True)
    
    Dim outRAF As RandomAccessFile
    outRAF.Initialize("D:\Downloads", outFile, False)
    
    ' Define block size as 1 MB.
    Dim BLOCK_SIZE As Int = 1024 * 1024
    ' Allocate buffers for plaintext, OTP, and encrypted output.
    Dim plainBuffer(BLOCK_SIZE) As Byte
    Dim otpBuffer(BLOCK_SIZE) As Byte
    Dim outBuffer(BLOCK_SIZE) As Byte
    
    Dim totalSize As Long = inRAF.Size
    Dim offset As Long = 0
    
    Do While offset < totalSize
        ' Calculate how many bytes to read for this block.
        Dim bytesToRead As Int = Min(BLOCK_SIZE, totalSize - offset)
        ' Read one block from the plaintext and the OTP file.
        inRAF.ReadBytes(plainBuffer, 0, bytesToRead, offset)
        otpRAF.ReadBytes(otpBuffer, 0, bytesToRead, offset)
        ' Process the block: encrypt each byte (addition modulo 256).
        For i = 0 To bytesToRead - 1
            Dim plainByte As Int = Bit.And(plainBuffer(i), 0xFF)
            Dim otpByte As Int = Bit.And(otpBuffer(i), 0xFF)
            outBuffer(i) = (plainByte + otpByte) Mod 256
        Next
        ' Write the encrypted block to the output file.
        outRAF.WriteBytes(outBuffer, 0, bytesToRead, offset)
        offset = offset + bytesToRead
    Loop

    inRAF.Close
    otpRAF.Close
    outRAF.Close
End Sub

'----------------------------------------------------------------
' Decrypts a file that was encrypted using addition modulo 256.
' Reads the encrypted and OTP files in 1 MB blocks, decrypts each block,
' and writes the resulting plain text in 1 MB blocks.
Sub DecryptFile(encryptedFile As String, otpFile As String, outFile As String)
    Dim inRAF As RandomAccessFile
    inRAF.Initialize("D:\Downloads", encryptedFile, True)
    
    Dim otpRAF As RandomAccessFile
    otpRAF.Initialize("D:\Downloads", otpFile, True)
    
    Dim outRAF As RandomAccessFile
    outRAF.Initialize("D:\Downloads", outFile, False)
    
    ' Define block size as 1 MB.
    Dim BLOCK_SIZE As Int = 1024 * 1024
    ' Allocate buffers for encrypted data, OTP, and decrypted output.
    Dim encryptedBuffer(BLOCK_SIZE) As Byte
    Dim otpBuffer(BLOCK_SIZE) As Byte
    Dim outBuffer(BLOCK_SIZE) As Byte
    
    Dim totalSize As Long = inRAF.Size
    Dim offset As Long = 0
    
    Do While offset < totalSize
        Dim bytesToRead As Int = Min(BLOCK_SIZE, totalSize - offset)
        inRAF.ReadBytes(encryptedBuffer, 0, bytesToRead, offset)
        otpRAF.ReadBytes(otpBuffer, 0, bytesToRead, offset)
        ' Process each byte of the block: decrypt using modulo arithmetic.
        For i = 0 To bytesToRead - 1
            Dim encryptedByte As Int = Bit.And(encryptedBuffer(i), 0xFF)
            Dim otpByte As Int = Bit.And(otpBuffer(i), 0xFF)
            outBuffer(i) = (encryptedByte - otpByte + 256) Mod 256
        Next
        ' Write the decrypted block to the output file.
        outRAF.WriteBytes(outBuffer, 0, bytesToRead, offset)
        offset = offset + bytesToRead
    Loop

    inRAF.Close
    otpRAF.Close
    outRAF.Close
End Sub
 
Last edited:

Tim Chapman

Active Member
Licensed User
Longtime User
I have updated the code to encrypt the plain text file one byte at a time as before, but to save it a megabyte at a time to speed it up and decrease use of the hard drive. It is now in the original post.
 
Top