Skip to content

Instantly share code, notes, and snippets.

@waz-git
Last active May 22, 2022 09:42
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save waz-git/b18de6f3c1c6c3943db87abb536baad1 to your computer and use it in GitHub Desktop.
Save waz-git/b18de6f3c1c6c3943db87abb536baad1 to your computer and use it in GitHub Desktop.
ObfuscateSampleSummary
using System;
using UnityEngine;
namespace ObfuscateSample
{
public class PlayerCredentialDTO
{
public string PrivateID;
}
public class PlayerCredentialDAO : IDisposable
{
private string _tableName;
private ILogger _logger;
private IntPtr _pDb = IntPtr.Zero;
public void Setup(string dbPath,string dbKey,string tableName,ILogger logger)
{
_tableName = tableName;
_logger = logger;
var flag = (int)(SQLiteOpenFlags.Create | SQLiteOpenFlags.ReadWrite);
SQLiteHelper
.Open(dbPath, out IntPtr pDb, flag, null);
_pDb = pDb;
#if !UNITY_EDITOR
SQLiteHelper
.Key(_pDb,dbKey);
#endif
}
public void Dispose()
{
if (_pDb != IntPtr.Zero)
{
SQLiteHelper.Close(_pDb);
}
}
private bool HasTable()
{
var query = $"SELECT count(*) FROM sqlite_master WHERE type='table' AND name='{_tableName}';";
//↑コードが↓に変換されてます
var pState = SQLiteHelper.Prepare(_pDb, query);
SQLiteHelper
.Step(pState)
.ThrowIfNotRowOrDone(_pDb,_tableName,query);
var result = SQLiteHelper.ColumnInt(pState, 0) == 1;
_logger?.Log($"DB HasTable {_tableName} / result : {result} , query : {query}");
SQLiteHelper
.Reset(pState)
.ThrowIfNotOK(_pDb,query);
SQLiteHelper
.Finalize(pState)
.ThrowIfNotOK(_pDb,query);
return result;
}
private void CreateTable()
{
var query = $"CREATE TABLE {_tableName} (id INTEGER PRIMARY KEY NOT NULL DEFAULT 1,privateId TEXT NOT NULL DEFAULT 0);";
SQLiteHelper
.Exec(_pDb,query,IntPtr.Zero, IntPtr.Zero, out IntPtr pError)
.ThrowExecResultIfNotOK(_pDb,query,pError);
}
public void SaveCredential(PlayerCredentialDTO dto)
{
var hasTable = HasTable();
if (!hasTable)
{
CreateTable();
}
var query = $"REPLACE INTO test (id,privateId) VALUES (1, '{dto.PrivateID}')";
SQLiteHelper
.Exec(_pDb,query,IntPtr.Zero, IntPtr.Zero, out IntPtr pError)
.ThrowExecResultIfNotOK(_pDb,query,pError);
}
public PlayerCredentialDTO LoadCredential()
{
var hasTable = HasTable();
if (!hasTable)
{
return null;
}
var query = $"SELECT * FROM {_tableName} limit 1;";
var pState = SQLiteHelper.Prepare(_pDb,query);
var result = default(PlayerCredentialDTO);
try
{
int resultCount = 0;
while (SQLiteHelper.Step(pState) == Result.Row)
{
resultCount++;
}
SQLiteHelper.Reset(pState)
.ThrowIfNotOK(_pDb, "Resetに失敗");
if (resultCount == 0)
{
return result;
}
result = new PlayerCredentialDTO();
while (SQLiteHelper.Step(pState) == Result.Row)
{
var privateId = SQLiteHelper.ColumnText(pState, 1);
result.PrivateID = privateId;
}
SQLiteHelper
.Reset(pState).
ThrowIfNotOK(_pDb,"Resetに失敗");
}
finally
{
SQLiteHelper
.Finalize(pState)
.ThrowIfNotOK(_pDb,"Finalizeに失敗");
}
return result;
}
}
}
using System;
using System.IO;
using System.Text;
using UnityEngine;
namespace ObfuscateSample
{
public class SaveSample : MonoBehaviour
{
private string _dbPath => Path.Combine(Application.persistentDataPath,"sampleData.db");
private string _dbKey = "sampleKey";
private void Start()
{
SRDebug.Init();
Debug.Log($"dbPath -> {_dbPath}");
using var dao = new PlayerCredentialDAO();
dao.Setup(_dbPath,_dbKey,"test",Debug.unityLogger);
var dto = dao.LoadCredential();
var hasCredential = dto is object;
if (hasCredential)
{
//ID表示
Debug.Log($"発行済み private id : {dto.PrivateID}");
return;
}
//秘匿したい情報
var privateId = Guid.NewGuid().ToString();
var credential = new PlayerCredentialDTO(){PrivateID = privateId};
dao.SaveCredential(credential);
//ID表示
Debug.Log($"新規発行 private id : {credential.PrivateID}");
}
}
}
using System;
using System.Runtime.InteropServices;
using System.Text;
using Sqlite3DatabaseHandle = System.IntPtr;
using Sqlite3BackupHandle = System.IntPtr;
using Sqlite3Statement = System.IntPtr;
using System.Runtime.CompilerServices;
namespace ObfuscateSample
{
/// <summary>
/// 参考
/// https://www.sqlite.org/rescode.html
/// https://github.com/praeclarum/sqlite-net/blob/ff6507e2accd79ab60aa84a1039215884e4118fa/src/SQLite.cs#L4267
/// </summary>
public enum Result : int
{
OK = 0,
Error = 1,
Internal = 2,
Perm = 3,
Abort = 4,
Busy = 5,
Locked = 6,
NoMem = 7,
ReadOnly = 8,
Interrupt = 9,
IOError = 10,
Corrupt = 11,
NotFound = 12,
Full = 13,
CannotOpen = 14,
LockErr = 15,
Empty = 16,
SchemaChngd = 17,
TooBig = 18,
Constraint = 19,
Mismatch = 20,
Misuse = 21,
NotImplementedLFS = 22,
AccessDenied = 23,
Format = 24,
Range = 25,
NonDBFile = 26,
Notice = 27,
Warning = 28,
Row = 100,
Done = 101
}
/// <summary>
/// 参考
/// https://www.sqlite.org/rescode.html
/// https://github.com/praeclarum/sqlite-net/blob/ff6507e2accd79ab60aa84a1039215884e4118fa/src/SQLite.cs#L4302
/// </summary>
public enum ExtendedResult : int
{
IOErrorRead = (Result.IOError | (1 << 8)),
IOErrorShortRead = (Result.IOError | (2 << 8)),
IOErrorWrite = (Result.IOError | (3 << 8)),
IOErrorFsync = (Result.IOError | (4 << 8)),
IOErrorDirFSync = (Result.IOError | (5 << 8)),
IOErrorTruncate = (Result.IOError | (6 << 8)),
IOErrorFStat = (Result.IOError | (7 << 8)),
IOErrorUnlock = (Result.IOError | (8 << 8)),
IOErrorRdlock = (Result.IOError | (9 << 8)),
IOErrorDelete = (Result.IOError | (10 << 8)),
IOErrorBlocked = (Result.IOError | (11 << 8)),
IOErrorNoMem = (Result.IOError | (12 << 8)),
IOErrorAccess = (Result.IOError | (13 << 8)),
IOErrorCheckReservedLock = (Result.IOError | (14 << 8)),
IOErrorLock = (Result.IOError | (15 << 8)),
IOErrorClose = (Result.IOError | (16 << 8)),
IOErrorDirClose = (Result.IOError | (17 << 8)),
IOErrorSHMOpen = (Result.IOError | (18 << 8)),
IOErrorSHMSize = (Result.IOError | (19 << 8)),
IOErrorSHMLock = (Result.IOError | (20 << 8)),
IOErrorSHMMap = (Result.IOError | (21 << 8)),
IOErrorSeek = (Result.IOError | (22 << 8)),
IOErrorDeleteNoEnt = (Result.IOError | (23 << 8)),
IOErrorMMap = (Result.IOError | (24 << 8)),
LockedSharedcache = (Result.Locked | (1 << 8)),
BusyRecovery = (Result.Busy | (1 << 8)),
CannottOpenNoTempDir = (Result.CannotOpen | (1 << 8)),
CannotOpenIsDir = (Result.CannotOpen | (2 << 8)),
CannotOpenFullPath = (Result.CannotOpen | (3 << 8)),
CorruptVTab = (Result.Corrupt | (1 << 8)),
ReadonlyRecovery = (Result.ReadOnly | (1 << 8)),
ReadonlyCannotLock = (Result.ReadOnly | (2 << 8)),
ReadonlyRollback = (Result.ReadOnly | (3 << 8)),
AbortRollback = (Result.Abort | (2 << 8)),
ConstraintCheck = (Result.Constraint | (1 << 8)),
ConstraintCommitHook = (Result.Constraint | (2 << 8)),
ConstraintForeignKey = (Result.Constraint | (3 << 8)),
ConstraintFunction = (Result.Constraint | (4 << 8)),
ConstraintNotNull = (Result.Constraint | (5 << 8)),
ConstraintPrimaryKey = (Result.Constraint | (6 << 8)),
ConstraintTrigger = (Result.Constraint | (7 << 8)),
ConstraintUnique = (Result.Constraint | (8 << 8)),
ConstraintVTab = (Result.Constraint | (9 << 8)),
NoticeRecoverWAL = (Result.Notice | (1 << 8)),
NoticeRecoverRollback = (Result.Notice | (2 << 8))
}
/// <summary>
/// 参考
/// https://www.sqlite.org/c3ref/open.html
/// </summary>
[Flags]
internal enum SQLiteOpenFlags
{
ReadOnly = 1, ReadWrite = 2, Create = 4,
NoMutex = 0x8000, FullMutex = 0x10000,
SharedCache = 0x20000, PrivateCache = 0x40000,
ProtectionComplete = 0x00100000,
ProtectionCompleteUnlessOpen = 0x00200000,
ProtectionCompleteUntilFirstUserAuthentication = 0x00300000,
ProtectionNone = 0x00400000
}
public sealed class SQLiteException : Exception
{
public Result Result { get;}
public ExtendedResult ErrorCode { get; }
public SQLiteException (Result result,ExtendedResult errorCode, string message) : base ($"Result : {result}, ExtendedResult : {errorCode}, "+message)
{
Result = result;
ErrorCode = errorCode;
}
public SQLiteException (Result result, string message) : base ($"Result : {result}, "+message)
{
Result = result;
ErrorCode = 0;
}
public SQLiteException (string message) : base (message)
{
ErrorCode = 0;
}
}
/// <summary>
/// 参考
/// https://www.sqlite.org/capi3ref.html
/// https://github.com/praeclarum/sqlite-net/blob/ff6507e2accd79ab60aa84a1039215884e4118fa/src/SQLite.cs#L4265
/// </summary>
internal sealed class SQLiteHelper
{
#region SQLite DLL ------------------------------------------------------------------------------------------
#if UNITY_IOS
const string Dllimport = "__Internal";
#elif UNITY_ANDROID
const string Dllimport = "sqlcipher";
#else
const string Dllimport = "sqlite3";
#endif
[DllImport(Dllimport, EntryPoint = "sqlite3_open_v2",CallingConvention = CallingConvention.Cdecl)]
private static extern int _sqlite3_open_v2(string filename, out IntPtr db, int flags, string zvfs);
[DllImport(Dllimport, EntryPoint = "sqlite3_close_v2",CallingConvention = CallingConvention.Cdecl)]
private static extern int _sqlite3_close_v2(IntPtr db);
[DllImport(Dllimport, EntryPoint = "sqlite3_prepare_v2",CallingConvention = CallingConvention.Cdecl)]
private static extern int _sqlite3_prepare_v2(IntPtr db, string zSql, int nByte, out IntPtr ppStmpt, IntPtr pzTail);
[DllImport(Dllimport, EntryPoint = "sqlite3_step",CallingConvention = CallingConvention.Cdecl)]
private static extern int _sqlite3_step(IntPtr stmHandle);
[DllImport(Dllimport, EntryPoint = "sqlite3_reset",CallingConvention = CallingConvention.Cdecl)]
private static extern int _sqlite3_reset(IntPtr stmHandle);
[DllImport(Dllimport, EntryPoint = "sqlite3_finalize",CallingConvention = CallingConvention.Cdecl)]
private static extern int _sqlite3_finalize(IntPtr stmHandle);
[DllImport(Dllimport, EntryPoint = "sqlite3_column_int",CallingConvention = CallingConvention.Cdecl)]
private static extern int _sqlite3_column_int(IntPtr stmHandle, int iCol);
[DllImport(Dllimport, EntryPoint = "sqlite3_column_text",CallingConvention = CallingConvention.Cdecl)]
private static extern IntPtr _sqlite3_column_text(IntPtr stmHandle, int iCol);
[DllImport(Dllimport, EntryPoint = "sqlite3_exec",CallingConvention = CallingConvention.Cdecl)]
private static extern int _sqlite3_exec(IntPtr db, string sql, IntPtr callback, IntPtr args, out IntPtr errorMessage);
[DllImport(Dllimport, EntryPoint = "sqlite3_errmsg",CallingConvention = CallingConvention.Cdecl)]
private static extern IntPtr _sqlite3_errmsg(IntPtr db);
[DllImport(Dllimport, EntryPoint = "sqlite3_extended_errcode",CallingConvention = CallingConvention.Cdecl)]
private static extern int _sqlite3_extended_errcode(IntPtr db);
// sqlcipher
[DllImport(Dllimport, EntryPoint = "sqlite3_key",CallingConvention = CallingConvention.Cdecl)]
private static extern int _sqlite3_key(IntPtr db, string key, int len);
#endregion
#region Operator
public static Result Open (string filename, out Sqlite3DatabaseHandle db,int flags, string vfsName)
{
return (Result)_sqlite3_open_v2(filename, out db,flags,vfsName);
}
public static Result Close (Sqlite3DatabaseHandle db)
{
return (Result)_sqlite3_close_v2(db);
}
public static Sqlite3Statement Prepare (Sqlite3DatabaseHandle db, string query)
{
var cnt = System.Text.Encoding.GetEncoding("UTF-8").GetByteCount(query);
var result = (Result)_sqlite3_prepare_v2 (db, query,cnt, out Sqlite3Statement stmt ,IntPtr.Zero);
if (result != Result.OK)
{
result.ThrowIfNotOK(db, $"_sqlite3_prepare_v2 result not ok, query : {query}");
}
return stmt;
}
public static Result Step (Sqlite3Statement stmt)
{
return (Result)_sqlite3_step(stmt);
}
public static Result Reset (Sqlite3Statement stmt)
{
return (Result)_sqlite3_reset (stmt);
}
public static Result Finalize (Sqlite3Statement stmt)
{
return (Result)_sqlite3_finalize (stmt);
}
public static int ColumnInt (Sqlite3Statement stmt, int index)
{
return _sqlite3_column_int (stmt, index);
}
public static string ColumnText (Sqlite3Statement stmt, int index)
{
var pt = _sqlite3_column_text(stmt, index);
return Marshal.PtrToStringAnsi(pt);
}
public static Result Exec(Sqlite3DatabaseHandle db, string query, IntPtr callback, IntPtr args,
out IntPtr errorMessage)
{
return (Result)_sqlite3_exec(db, query, callback, args,out errorMessage);
}
public static Result Key(Sqlite3DatabaseHandle db, string key)
{
return (Result)_sqlite3_key(db, key, key.Length);
}
public static string GetErrorMassage (Sqlite3DatabaseHandle pt)
{
var error = _sqlite3_errmsg (pt);
return Marshal.PtrToStringAnsi(error);
}
public static ExtendedResult GetErrorCode (Sqlite3DatabaseHandle pt)
{
return (ExtendedResult)_sqlite3_extended_errcode(pt);
}
#endregion
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment