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.
 
Cookies are required to use this site. You must accept them to continue using the site. Learn more…