How can I JSON encode a table, encrypt it, save it, and restore it?

That line is in resources, I didn’t write it. I think what error is from plugin itself.

Why don’t I see a complete test project attached to this thread yet?

Make a tiny project demonstrating the issue. zip it up, and attach it to the thread. Then folks can download it, run it, fix it, and reupload it.

Ya, better you share which part of the code has error.

Here is an example with decryption. Note the mime.unb64 and cipher:decrypt

local testString = {
  version = 1,
}
local pass = "somePass"
-- local iv = '1234567890123456'			-- 

testString = json.encode( testString )

local encryptedData = b64encode( cipher:encrypt( testString, pass ) )
-- print( encryptedData )
local path = system.pathForFile( "data.json", system.TemporaryDirectory )	--system.ResourseDirectory )
-- print(path)
local file = io.open( path, "w" )
-- print( file )

if file then
	file:write( encryptedData )
	io.close( file )
end





--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
local file = io.open( path, "r" )
print( file )

if file then
	local readString = file:read(  )
	io.close( file )


	print( readString )

	-- Decrypt the string
	local decryptedString = cipher:decrypt( mime.unb64(readString), pass ) 
	print( decryptedString )

	local decryptedTable = json.decode(decryptedString)
	print( json.prettify(decryptedTable) )
	
end

ok, I fixed encryption, but there is still one problem I get an error what data from file is nil.
Mini project:Encryption.zip (66.4 KB)

Feedback before solution

  • You could have saved a TON of time making a tiny sample in the beginning. I personally prefer a downloadable example 10x over having to type in pasted code. So I abstained from helping till you provided downloadable code.

  • You re-made some mistakes that were corrected for you previously. You cannot write to the resource directory, but your example tries to. (also you misspelled it)

  • You started the thread with one question, but then added a new one which didn’t match the title. So, I updated the title of the thread to better match the entire discussion. This will help future readers and make the input folks have given more worthwhile.

Fixes
Before I started on this, I copied the contents of main.lua into ex0_original.lua, then required ex0_original.lua from main.

As I made changes, I made new copies of the file before applying changes. This will allow you to see the progression of the changes.

I also copied a few extensions from ssk and required them at the top of main.lua. You don’t have good table printing code and you wrote your own file save/restore code which is not necessary. There are dozens of solid working modules to save/load files. Just use one from the web or SSK.

There are 5 variations on your code (the first four are in separate example files):

    1. ex0_original.lua - Original version of your code.
    1. ex1_original_minus_encryption.lua - Original version minus encryption. I found you had saving to file wrong so I made comments and fixed it.
    1. ex2_original_all_fixed.lua - version 1 + re-added encryption
    1. ex3_better_with_ssk.lua - Used function approach to code + some SSK extensions.

Lastly, I converted the code in ex3_better_with_ssk.lua to a module tableEncrypt.lua

If you look in main.lua, you’ll see example a section labeled ‘4 - All fixed and reduced using SSK then made into a module’ where I show the module in action, reproducing your example in just a few lines.

Encryption2.zip (15.6 KB)

tableEncrypt.lua (uses SSK to save/load file)

local timer = require( "timer" )
local composer = require( "composer" )
local json = require( "json" )
local ssl = require( "plugin.openssl" )
local cipher = ssl.get_cipher( "aes-256-cbc" )
local mime = require( "mime" )

local debugEn = true

local tableEncrypt = {}

--
-- saveEncryptedTable() 
--
tableEncrypt.saveEncryptedTable = function ( srcTable, fileName, password, baseDir  )
   password = password or "somePass"
   baseDir  = baseDir or system.DocumentsDirectory

   if(debugEn) then table.dump( srcTable, "(save) srcTable" ) end

   -- 1. JSON encode the table
   local encodedTable = json.encode( srcTable )
   if(debugEn) then print( '(save) encodedTable: ', encodedTable ) end

   -- 2. Encrypt the encoded data.
   local encryptedData = mime.b64( cipher:encrypt( encodedTable, password ) )
   if(debugEn) then print( '(save) encryptedData: ', encryptedData ) end

   -- 3. Write encrypted data to a file.
   io.writeFile( encryptedData, fileName, baseDir )

   return encryptedTable
end

--
-- restoreEncryptedTable() 
--
tableEncrypt.restoreEncryptedTable = function( fileName, password, baseDir )
   password = password or "somePass"
   baseDir  = baseDir or system.DocumentsDirectory

   -- 1. Load encrypted encrypted data from file.
   local encryptedData = io.readFile( fileName, baseDir )
   if(debugEn) then print( '(restore) encryptedData: ', encryptedData ) end

   -- 2. Decrypt to encoded JSON data.
   local encodedTable = cipher:decrypt( mime.unb64( encryptedData ), password )
   if(debugEn) then print( '(restore) encodedTable: ', encodedTable ) end

   -- 3. Decode JSON data to table.
   local restoredTable = json.decode(encodedTable)
   if(debugEn) then table.dump( restoredTable, "(restore) restoredTable" ) end


   return restoredTable   
end

return tableEncrypt

Sample usage of module

local tableEncrypt = require "tableEncrypt"
local originalTable = {
   version = 4,
   playerLevel = 100,
   music = 0,
   sfx = 0,
}
tableEncrypt.saveEncryptedTable( originalTable, "data4.json", "myPassword" )

local myTable = tableEncrypt.restoreEncryptedTable( "data4.json", "myPassword" )

local version = display.newText( myTable.version, 100, 100, native.systemFont, 20)
1 Like

I also further reduced your example, by getting rid of some folders and stuff in build.settings that wasn’t needed for an in-simulator demo.

Thanks, and that documents directory is where user sees his documents?
Is there any other directory, so user will not delete it accidentally?

No. The documents folder is a private folder specific to that app for storing files you don’t want auto-deleted.

If you want them auto-deleted when the app is closed, put them in the temporary folder.

The user won’t see these files unless they root their device and have an app to explore app folders.

This all depends on the platform. For iOS/Android, they’d need to root the device. For Windows, the locally saved data will be accessible normally. Also, while temporary folder will be wiped on iOS/Android, they won’t be wiped on desktop platforms, etc.

1 Like

@cruizea5,

If you’re trying to do exactly what this thread is talking about, you can simply download the example I modified: https://forums.solar2d.com/uploads/short-url/esk6dMUZy4VeQr3oSrd4E1mWtTX.zip

It works.

1 Like

I tried to implement this to my project and finally I did it. But can I find file what is in documents directory to check is it writing it or not?

Nevermind, found that in documentation