C#解析SQLCipher数据库

前言

       最近需要解析一个SQLCipher数据库文件,是带密码的那种,网上查询了好多资料,大多数都是说要在VS上查找“SQLCipher”数据库的NuGet包,然后直接就可以用了,但是我多次尝试,都失败了,总是提示“file is not a database”,也许我的文件比较特殊吧。

解决方案

搜资料时搜到了这个:SqlCipher: Sqlite 的加密版本SqlCipher加载 数据库

通过调用“sqlcipherbd.dll”动态库来解析SQLCipher数据库,该动态库还是C/C++开发的,支持C#、C、C++等语言的调用。

参考原始资料中代码写的比较乱,不方便看,我自己写了一个小demo实现了一下。

 下面贴出来读取数据库的代码:

        private void button1_Click(object sender, EventArgs e)
        {
            OpenFileDialog opendialog = new OpenFileDialog();
            if (opendialog.ShowDialog() != DialogResult.OK)
            {
                return;
            }


            IntPtr _connection = IntPtr.Zero;
            if (SqliteDLL.sqlite3_open(opendialog.FileName, out _connection) != SqliteDLL.SQLITE_OK)
                return;

            if (SqliteDLL.sqlite3_key(_connection, textBox1.Text, textBox1.Text.Length) != SqliteDLL.SQLITE_OK)
                return;

            IntPtr stmHandle;
            string strsql = "select * from menu";
            if (SqliteDLL.sqlite3_prepare_v2(_connection, strsql, strsql.Length, out stmHandle, IntPtr.Zero) != SqliteDLL.SQLITE_OK)
                return;

            int iColumnCount = SqliteDLL.sqlite3_column_count(stmHandle);
            DataTable dataTableTmp = new DataTable();
            for (int i = 0; i < iColumnCount; i++)
            {
                string columnName = Marshal.PtrToStringAnsi(SqliteDLL.sqlite3_column_name(stmHandle, i));
                dataTableTmp.Columns.Add(columnName);
            }

            /* 获取每行数据 */
            while (SqliteDLL.sqlite3_step(stmHandle) == SqliteDLL.SQLITE_ROW)
            {
                DataRow dataRowTmp = dataTableTmp.NewRow();
                for (int i = 0; i < iColumnCount; i++)
                {
                    byte[] byteArrayUnicode = Encoding.Unicode.GetBytes(Marshal.PtrToStringUni(SqliteDLL.sqlite3_column_text(stmHandle, i))); //转成UNICODE编码
                    dataRowTmp[i] = Encoding.UTF8.GetString(byteArrayUnicode);
                }
                dataTableTmp.Rows.Add(dataRowTmp);
            }

            SqliteDLL.sqlite3_finalize(stmHandle);
            SqliteDLL.sqlite3_close(_connection);

            dataGridView1.DataSource = dataTableTmp;
        }

这里是导入“sqlcipherbd.dll”动态库 API的代码:

        [DllImport(SQLCIPHERDLL, EntryPoint = "sqlite3_open", CallingConvention = CallingConvention.Cdecl)]
        public static extern int sqlite3_open(string filename, out IntPtr db);

        [DllImport(SQLCIPHERDLL, EntryPoint = "sqlite3_close", CallingConvention = CallingConvention.Cdecl)]
        public static extern int sqlite3_close(IntPtr db);

        [DllImport(SQLCIPHERDLL, EntryPoint = "sqlite3_key", CallingConvention = CallingConvention.Cdecl)]
        public static extern int sqlite3_key(IntPtr db, string key, int keyLen);

        [DllImport(SQLCIPHERDLL, EntryPoint = "sqlite3_prepare_v2", CallingConvention = CallingConvention.Cdecl)]
        public static extern int sqlite3_prepare_v2(IntPtr db, string zSql, int nByte, out IntPtr ppStmpt, IntPtr pzTail);

        [DllImport(SQLCIPHERDLL, EntryPoint = "sqlite3_step", CallingConvention = CallingConvention.Cdecl)]
        public static extern int sqlite3_step(IntPtr stmHandle);

        [DllImport(SQLCIPHERDLL, EntryPoint = "sqlite3_finalize", CallingConvention = CallingConvention.Cdecl)]
        public static extern int sqlite3_finalize(IntPtr stmHandle);

        [DllImport(SQLCIPHERDLL, EntryPoint = "sqlite3_errmsg", CallingConvention = CallingConvention.Cdecl)]
        public static extern IntPtr sqlite3_errmsg(IntPtr db);

        [DllImport(SQLCIPHERDLL, EntryPoint = "sqlite3_column_count", CallingConvention = CallingConvention.Cdecl)]
        public static extern int sqlite3_column_count(IntPtr stmHandle);

        [DllImport(SQLCIPHERDLL, EntryPoint = "sqlite3_column_name", CallingConvention = CallingConvention.Cdecl)]
        public static extern IntPtr sqlite3_column_name(IntPtr stmHandle, int iCol);

        [DllImport(SQLCIPHERDLL, EntryPoint = "sqlite3_column_type", CallingConvention = CallingConvention.Cdecl)]
        public static extern int sqlite3_column_type(IntPtr stmHandle, int iCol);

        [DllImport(SQLCIPHERDLL, EntryPoint = "sqlite3_column_int", CallingConvention = CallingConvention.Cdecl)]
        public static extern int sqlite3_column_int(IntPtr stmHandle, int iCol);

        [DllImport(SQLCIPHERDLL, EntryPoint = "sqlite3_column_text", CallingConvention = CallingConvention.Cdecl)]
        public static extern IntPtr sqlite3_column_text(IntPtr stmHandle, int iCol);

        [DllImport(SQLCIPHERDLL, EntryPoint = "sqlite3_column_double", CallingConvention = CallingConvention.Cdecl)]
        public static extern double sqlite3_column_double(IntPtr stmHandle, int iCol);

        [DllImport(SQLCIPHERDLL, EntryPoint = "sqlite3_column_blob", CallingConvention = CallingConvention.Cdecl)]
        public static extern IntPtr sqlite3_column_blob(IntPtr stmHandle, int iCol);

        [DllImport(SQLCIPHERDLL, EntryPoint = "sqlite3_column_bytes", CallingConvention = CallingConvention.Cdecl)]
        public static extern int sqlite3_column_bytes(IntPtr stmHandle, int iCol);

        [DllImport(SQLCIPHERDLL, EntryPoint = "sqlite3_bind_double", CallingConvention = CallingConvention.Cdecl)]
        public static extern int sqlite3_bind_double(IntPtr stmHandle, int idx, double value);

        [DllImport(SQLCIPHERDLL, EntryPoint = "sqlite3_bind_int", CallingConvention = CallingConvention.Cdecl)]
        public static extern int sqlite3_bind_int(IntPtr stmHandle, int idx, int value);

        [DllImport(SQLCIPHERDLL, EntryPoint = "sqlite3_bind_text", CallingConvention = CallingConvention.Cdecl)]
        public static extern int sqlite3_bind_text(IntPtr stmHandle, int idx, byte[] value, int length, IntPtr callback);

        [DllImport(SQLCIPHERDLL, EntryPoint = "sqlite3_bind_blob", CallingConvention = CallingConvention.Cdecl)]
        public static extern int sqlite3_bind_blob(IntPtr stmHandle, int idx, byte[] value, int valueLen, IntPtr callback);

完整的项目代码放进Gitee了:ReadSQLCipher: C#通过“sqlcipherbd.dll”读取SQLCipher数据库,动态库“sqlcipherbd.dll”是C/C++开发的,导出了API,支持C#、C、C++等语言的调用。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值