- 项目展示
- 动机背景
- 技术概览
- reference
- hack manual
- wechat design
- py-sqlcipher instruction
- extended
- 本项目合作伙伴
项目展示
获取所有微信好友信息
derived from hacked db: Contact/wccontact_new2.db
导出与微信好友的聊天记录
derived from hacked dbs: Message/msg_*.db
监控实时聊天
derived from real-time terminal
其他
动机背景
一切,都要从南川的计算机小群里 Shining Lavender
和 Le Penseur
同学聊到“爱”这个高深的话题,继而聊到了“soulmate”,而我最近恰好看了《Intouchables》:
所以和 Le Penseur
同学一下探讨到了凌晨……
上半场刚结束,基友群表示对这个话题也很感兴趣,遂我们又来回肝完了半个通宵。
下半场也结束后,我发现我很想把这些闪烁智慧与思考、彭拜着荷尔蒙与伤感的青春文字记录整理下来,但是无奈微信未能提供满足我这种需求的便利。
自然而然地,作为一名合格的程序员,兵来将挡水来土掩,我们又上场了……
历时一天,彻底拿下!
技术概览
思路还是比较通用的。
github search until wechat-decipher-macos
首先,第一步,去 github
搜索是否已经有破解微信聊天记录相关的开源仓库,结果,应有尽有,一应尽全 - Search · wechat history:
可以看到,至少在这一页前几个仓库中,安卓、iOS、mac 都有,windows 倒不确定。
我目前手机用的是安卓,电脑是 mac,但我用电脑比较多,所以我倾向于选择 mac 的方案,于是第一选择这个仓库 - nalzok/wechat-decipher-macos: Scripts to extract chat history from WeChat on macOS
不过这个仓库,起手难度可不低,仓库介绍十分简练,但真的是字字珠玑!
对于用户(我)来说,这个仓库的主要功能在前三者,一定要仔细理解,每个字都很宝贵:
macos/eavesdropper.d
macos/eavesdropper.d
是用于实时、高速打印微信与数据库之间的信息流的,具体什么样子呢?我运行一下给你们看一下。
可以看到,我在微信中发送的聊天内容,会被明文显示到控制台中,并且在不同的时间点被打印了两遍。
当然,这不是微信自己打印的,是我们(他的)脚本打的,并且把结构体都打出来了,这个结构体和最终存到数据库里的数据结构基本是差不多的。
比如这是我们数据库中的样子:
但是,由于这是用于实时的,也就是过去的就没有了,所以不满足我的需求,因为我也没有深究这个脚本(比如为啥打印两次,强迫症的我接受不了,至少接受不了这么大面积的冗余)。
macos/dbcracker.d
其实我一开始没有看懂macos/dbcracker.d
这个脚本用来干啥的,并且以为第四个脚本devel/xlogger.d
才是我的目标,但显然,这个想法错的离谱。
cracker
是“撕裂者”的意思,dbcracker
就是“数据库撕裂者”,听起来还是很可怕吧!
事实上,它真地很可怕 !
而且,我后续所有的工作都是基于它完成的!
但它的操作,就没有第一个脚本 macos/eavesdropper.d
那么容易上手了。
首先,注意它的描述:Since it can only capture secrets when WeChat.app opens these files, you need to perform a login while the script is running.
,也就是你需要先运行脚本,然后重启微信,才能看到效果。
不过经过我的测试,正确流程是这样的,先退出微信登录(或者直接杀掉,然后启动),保留微信在登录界面(但还没有登录),接着运行脚本(否则会报基于没有进程导致的后续错误),然后扫码登录成功,这个时候就能飞速地看到命令行有很多数据在跑了,其实就是微信所有(大部分)的数据库的文件位置、秘钥、参数等。
值得注意的是,秘钥是用来干啥的。
一般用惯了mysql
或者mongodb
之类数据库的人(别”人“了,就是我),其实根本不知道这个秘钥(既然不是用户密码)用来干嘛,这才是本项目的第一大难点。
这个时候,细心地读下一句:Simply copy & paste the script output to invoke SQLCipher and supply the respective PRAGMAs.
,翻译过来就是,把命令行的输简单地出复制粘贴,已启动SQLCipher
并分别用于PRAGMA
。
很绕,也一脸懵逼是不,是就对了!
答案在那个超链接 sqlcipher/sqlcipher: SQLCipher is a standalone fork of SQLite that adds 256 bit AES encryption of database files and other security features. 上,所以你为了使用 A 项目,不得不去先啃 B 项目了。
但实际上,sqlcipher
更难看懂,尤其是一上来就教你怎么编译,非常硬核(然而还有坑):
编就编吧,还有依赖,看看:
You must define SQLITE_HAS_CODEC and either SQLITE_TEMP_STORE=2 or SQLITE_TEMP_STORE=3
You will need to link against a support cryptographic provider (OpenSSL, LibTomCrypt, CommonCrypto/Security.framework, or NSS)
让我们定义变量(一开始以为是环境变量,后来发现是头文件内部变量),还要链接一个加密库……
一脸懵逼吧。
我一开始也看不懂,然后瞎编了一下。
结果果然报错了……
接着就一顿乱搜,然后找到了对本项目影响最大的一篇博客:- (25 条消息) Mac 终端使用 Sqlcipher 加解密基础过程详解_Martin.Mu `s Special Column-CSDN 博客_mac sqlcipher。
这个事实充分证明,只要你想干的事情足够大众,你就能找到非常不错的伙伴,或者说,前辈。
该文章基本包括了sqlcipher
如何编译、安装的问题,以及(非常前瞻性地)解决了里面的一些坑,节省了我可期的很多时间。
基于这篇文章,我熟悉了 sqlcipher
的使用,意识到 sqlcipher
是 sqlite3
的加密版,每个数据库可以独立地用一个KEY
加密,然后还可以解密,并导出无加密版本的sqlite3
。
所以在那之后,我才真正地意识到 macos/dbcracker.d
是用来干什么的:
- 用该脚本,通过监听微信启动时打开数据库的动作,暴露微信所有数据库的文件位置与秘钥信息
- 接下来数据库秘钥都有了,做啥就取决于自己了,比如说把所有好友的信息都导出成一张 excel 表这种
以下是该脚本监控到的数据库,与微信实际数据库对比。
Almost all (especially the core ones, such as Contacts/Messages relative) the tables are tracked.
Hence, it's pretty good for our further work.
Also, the db-list.txt
is derived from:
And the db-list-tracked.txt
is derived from:
The track.log
is derived from:
pcbakchat/gather.d
这个脚本其实也挺有用的,它能捕获备份时的数据流。
在说这个之前,我们有必要明确一下微信中的备份是啥意思(尤指 mac 平台)。
其实是这样的, 由于登录设备差异,同一个微信账户在不同设备(win、mac、ios、android)上的聊天记录是不完全一致的,一般手机上的才是完整的,电脑上(如果你没有一直登)是不完整的。
所以 mac 平台上的备份就包括
- 从手机备份到 mac
- 从 mac 备份到手机
我一开始以为备份是指把 mac 上的数据备份到另一个文件夹内,这个理解是不对的,其实如果去看微信的数据库设计部分,每个数据库是有单独的.db.bak
的,尽管不大(也许里面压根就没有备份的数据,或者是压缩后的),但微信确实都有数据库级别备份的意图。
那无论是从手机备份到 mac 还是从 mac 备份到手机,都涉及到两台机器之前通信的问题,再明确一点,他们要彼此在同一个局域网内,用 socket 进行文件传送的。
所以其实 pcbakchat/gather.d
就是劫持这部分局域网通信,把所有要备份的聊天记录都曝光出来,达到了给我们自己处理的目的。
具体可以见本仓库对备份部分的详细说明 - wechat-decipher-macos/devel at main · nalzok/wechat-decipher-macos:
可以看到还是比较复杂的,我一开始本来是走的这个思路,但是当时我还没对微信的数据库有较高的认识,所以当时这个方案跑起来了但是我没用。
其实这个方案应该最适合我的需求,因为我想获得的好友/群组的信息是已知的、数量不多的,我可以分别对这几个好友/群组进行备份动作,这样可以很方便地直接得到与他们的聊天记录(还可以在备份时选择时间,并且是手机上的聊天记录,也就是更完整)。
但考虑到我后来一直在研究数据库加解密上,并且在获得数据库秘钥之后,通过操作数据库也能获得我所有想要的聊天记录(因为当时我聊天的部分恰好都在 mac 上),所以 macos/dbcracker.d
已经能够满足我的要求。
所以本篇也会重点基于 macos/dbcracker.d
进行介绍,尽管 pcbakchat/gather.d
更适合导出与指定好友的(更完整的)聊天记录,更具有“社会”价值,但前者更具有“娱乐”(bushi,研究)价值。
devel/xlogger.d
这个其实就是把 mac 微信上所有的消息流都劫持了,打印出非常多的东西,所以只适合“黑客”自己二度开发相要的功能。
我们的需求没必要用这个,并且它一打开,微信就卡死了……可能是影响了微信的运行速度,然后假死,这是异常行为,可能有封号风险,所以谨慎。
总结
我们全部的工作,主要还是建立在 - nalzok/wechat-decipher-macos: Scripts to extract chat history from WeChat on macOS 的基础上,Qingyao Sun
做了出色的工作(尽管部分地方有一些瑕疵),没有他精致(还记得我怎么评价的吗?“字字珠玑”)的项目文档,与合理的项目结构设计,我是不太可能一到两天就“攻破”微信的数据库的,感谢!
update@2022-02-08: 关于加密字段
备份数据库的cipher_page_size
不是默认值(1024),而是 4096!
所以原作中打印出这些信息是很有必要的!
reference
如果您想自己攻破微信的数据库系统,以下是一些我认为比较核心的参考资料,包括各大平台的。
万变不离其中的是,微信的数据库使用的是基于
sqlite3
加密的sqlcipher
,并且是sqlcipher 3 defaults
配置,所以理解与熟悉该数据库才是全部工作的最大攻坚战。当你攻破之后,怎么做,就是你的事情了。⚠️ 友情提醒:不要乱动微信的数据库,否则引起的一切后果,与本文无关,本文不涉及任何修改微信数据库的实现
各大平台仓库合集
mac 版
windows 版
- windows 版详细教程:[原创]PC 版微信数据库解密详细教程-软件逆向-看雪论坛-安全社区|安全招聘|bbs.pediy.com
ios 版
- 知乎日报 - 知乎
- stomakun/WechatExport-iOS: Save iOS WeChat history as HTML or TXT with neat layout and picture & audio support.
sqlcipher
相关
sqlcipher
官方版本(提供了启动指引):sqlcipher/sqlcipher: SQLCipher is a standalone fork of SQLite that adds 256 bit AES encryption of database files and other security features.python 版本
sqlcipher
: rigglemania/pysqlcipher3: Python 3 bindings for SQLCipher✨可视化软件(前期验证登录帮了大忙):Downloads - DB Browser for SQLite
sqlcipher
(商业)官方网站:SQLCipher - Zetetic
pragma
相关
pragma
是sqlite3
中的一种关键字,具体我也不太懂,我们项目只需要会用很简单的几条语句即可,是操作sqlcipher
必须的。
- ✨✨
pragma
核心语句(包括算法部分):SQL Pragmas | SQLite3 Multiple Ciphers - ✨
sqlcipher
相关接口实现:sqlcipher/crypto_impl.c at 4f37c817eb99e18e4fdc8ac63d67ac33610d66be · Tencent/sqlcipher pragma
部分语句(没有算法部分):Pragma statements supported by SQLitepragma
部分语句(也没有算法部分):SQLite PRAGMA | 菜鸟教程- 其他
pragma
相关问题:如何降级加密的 Sqlite 数据库文件 - 掘金
frida
相关
frida
是用于逆向的,原以为要用到,后来发现没有(至少我的应用级别没用到),也是捏了一把冷汗。以防需要,所以也补一份。项目底层监控微信部分,应该是用到了frida
的。
hack manual
download sqlite
download any sqlite versions from here SQLite Download Page or directly download mac (x86) version from https://www.sqlite.org/2022/sqlite-tools-osx-x86-3370200.zip
test sqlite
unzip the downloaded sqlite zip, and test the sqlite.
➜ sqlite-tools-osx-x86-3370200 tree .
.
├── sqldiff
├── sqlite3
└── sqlite3_analyzer
0 directories, 3 files
install openssl
to replace the built-in libressl
on MacOS
!!!warning brew
need to be pre-installed
install openssl
via brew
brew install openssl
config openssl
into path
According to the brew instruction on openssl:
We can directly write all the three commands into shell and make them work:
# if you use bash, change $SHELL to be `~/.bashrc`
SHELL=~/.zshrc
cat <<EOF >> $SHELL
heredoc> export PATH="/usr/local/opt/openssl@3/bin:$PATH"
heredoc> export LDFLAGS="-L/usr/local/opt/openssl@3/lib"
heredoc> export CPPFLAGS="-I/usr/local/opt/openssl@3/include"
heredoc> export PKG_CONFIG_PATH="/usr/local/opt/openssl@3/lib/pkgconfig"
heredoc> EOF
source $SHELL
result
before changing openssl, the default openssl is libressl:
after that it becomes openssl:
!!!tip 因为将 openssl 的路径加入了 path(并且在默认搜索路径之前),所以现在输入openssl
会优先检索到我们的 openssl,如果想换回默认的libressl
,则一方面可以在~/.zshrc
配置文件中把我们新加入的几句话注释掉,这样每次重启 SHELL 就不会有;同时,我们还要在 SHELL 中重置一下 path,如下:

参考:
- [How to Reset the PATH Variable on Mac to Default macOS PATH](https://techpp.com/2021/09/13/reset-path-variable-on-mac-guide/)
- [macos - How do I reset the $PATH variable on Mac OS X? - Super User](https://superuser.com/questions/121870/how-do-i-reset-the-path-variable-on-mac-os-x)
confirm openssl
According to the brew install openssl
command result, our openssl source codes are under /usr/local/Cellar/openssl@xxx
:
Have a check:
!!!tip 可以看到,我们其实默认是有一个openssl@1.1
的,然后我们新装了一个openssl@3
,所以实际上我 follow 的那个帖子并不完全正确。
至少在我们安装homebrew后,就已经有了`openssl`(不单单是mac的`libressl`)。
这意味着其实我们(可能)没有必要再安装一个`openssl`,直接把目前这个`openssl`相关的信息写入环境变量即可。(待验证这种方式是否有效)
compile sqlcipher
在我没有define SQLITE_HAS_CODEC and either SQLITE_TEMP_STORE=2 or SQLITE_TEMP_STORE=3
之前(引申阅读: 1. VC++下的 sqlite 数据库加密 | 离别歌, 2. SQLite Forum: SQLITE_HAS_CODE is gone?),运行的命令行会报错:
./configure --enable-tempstore=yes CFLAGS="-DSQLITE_HAS_CODEC" \
LDFLAGS="/usr/local/Cellar/openssl@3/3.0.1/lib/libcrypto.a"
但你定义上述变量还比较麻烦,要去某个.h
里,我都不知道它们在哪……其次,也不一定只是定义这个问题。
在我们的中文教程 (25 条消息) Mac 终端使用 Sqlcipher 加解密基础过程详解_Martin.Mu `s Special Column-CSDN 博客_mac sqlcipher 里他摸索出来的结果是这样的:
所以我基于他给出的命令行改成了如下(1. 删除了--prefix=yourlibdir
这个参数; 2. 修改了LDFLAGS
参数为我们实际的libcrypto.a
位置):
./configure --disable-tcl --disable-shared --enable-static=yes --enable-tempstore=yes --with-crypto-lib=none CFLAGS="-DSQLITE_HAS_CODEC -DSQLCIPHER_CRYPTO_OPENSSL" LDFLAGS="/usr/local/Cellar/openssl@3/3.0.1/lib/libcrypto.a"
然后一下就编译成功了!
接着就是make
一下,最终会生成sqlcipher
可执行文件:
以上就代表我们的编译过程顺利完成。
UPDATE: 静态编译
刚刚那个编译好像属于动态编译,后续我在编译 python 版本的pysqlcipher3
的时候又出现了ld: library not found for -lsqlcipher
的问题:
所以还是静态编译可能比较好。
重新回顾一下 sqlcipher
的编译教程,我们只需要知道 libcrypto.a
的位置就可以了。
(南川)注意看我是怎么找到 libcrypto.a
的位置的,当我只知道他在Cellar
下的时候。(其中的realpath
命令需要brew install coreutils
)
接着拷贝该位置到安装参数内。
(.pyenv) ➜ sqlcipher git:(master) ✗ ./configure --enable-tempstore=yes CFLAGS="-DSQLITE_HAS_CODEC" LDFLAGS="/usr/local/Cellar/openssl@3/3.0.1/lib/libcrypto.a"
但是报错了:
这个问题其实正好就是我们动态编译错过了的但是博主碰到了的问题:
跟着他的经验,也别管他的命令行怎么写的,加上参数:
(.pyenv) ➜ sqlcipher git:(master) ✗ ./configure --enable-tempstore=yes CFLAGS="-DSQLITE_HAS_CODEC" LDFLAGS="/usr/local/Cellar/openssl@3/3.0.1/lib/libcrypto.a" --with-crypto-lib=none
立即通过!然后再运行make install
即可。
注意,install
之后,可以看到,其实是把libsqlcipher.a
等写入到了/usr/local/lib
下面,这个路径要记得,以后其他库一般也会编到这里。
test sqlcipher
workflow
step 1. crypto a plain database (which is generated by our sqlite
before)
Among the commands, the attach database XXX as encrypted key YYY
would generate a database named XXX, which is encrypted by key YYY.
step2. test: operate on an encrypted database without key (expect: failure)
step3. test: dump the encrypted database into plain with key (expect: success)
step4. test: open the decrypted database without key (expect: success)
✨✨ decrypt database
DEPRECIATED: pragma config of sqlcipher 3 defaults
!!!warning 我的 sqlcipher
版本是 3.36.0
,这个版本默认是 sqlcipher 4
的配置了(盲猜),而腾讯的加密用的是 sqlcipher 3
,所以在解密文件时,必须将配置都对上(可以按照 GUI 软件DB Browser for SQLite
一一对上),否则会出现file is not a database
或 out of memory
等错误
PRAGMA cipher_compatibility = 3;
PRAGMA kdf_algorithm = 0;
PRAGMA hmac_algorithm = 0;
PRAGMA kdf_iter = 64000;
PRAGMA cipher_page_size = 1024;
ref
core ref of pragma statements, especially sqlcipher relative: SQL Pragmas | SQLite3 Multiple Ciphers
tencent forked sqlcipher: Tencent/sqlcipher at 4f37c817eb99e18e4fdc8ac63d67ac33610d66be
BEST-PRACTICE: pragma config of sqlcipher 3 defaults
As mentioned at: - rigglemania/pysqlcipher3: Python 3 bindings for SQLCipher, we only need to add one line of PRAGMA cipher_compatibility = 3"
after setting "PRAGMA key='password'"
.
Here is the tested result:
check salt of specific database file
usage
xxd -p -l 16 -g 0 '/path/to/foo.db'
sample
verification
ref
decrypt and dump specific database file
- open our custom hook script and get the database secret info:
copy the
PRAGMA XXX
statements for specific database filedump specific database file after decrypting
ATTACH DATABASE 'plaintext.db' AS plaintext KEY "";
SELECT sqlcipher_export("plaintext");
DETACH DATABASE plaintext;
ref
- How to decrypt the sqlcipher, when the version matchesencryption - How to decrypt an encrypted sqlcipher database file on command line? - Stack Overflow
test dumped database file (via sqlcipher
or sqlite3
)
Since the database dumped has been decrypted, so using sqlcipher
or sqlite3
are both ok!
!!!tip As a contrary, if we using sqlite3
to open an encrypted database file, then the PRAGMA
commands are always invalid, and there would be no way to decrypt the database.

wechat design
design of contact fields
以某好友资料为例:
对应的可以看到数据表信息为:
可以知道,最有用的字段主要如下:
gUsrName: wxid(自动、唯一标识号)
m_nsAliasName: 好友的注册id
nickname: 好友自己设置的对外显示的昵称
m_nsRemark: 你给好友设置的备注
其他还有一些拼音相关的有时也比较适合模糊搜索,不过全拼和简拼比较适合中文,英文的话全拼不变,简拼没有(另外也可以看到腾讯的命名规则也不统一,并且还中英文混杂……):
m_nsFullPY: 好友昵称全拼
m_nsShortPY: 好友昵称简拼
m_nsRemarkPYFull: 好友备注全拼
m_nsRemarkPYShort: 好友备注简拼
design of user id to contact id: md5
ref
IMPROVE: get self id
搜索自己的昵称,但是发现没有找到,说明contact
表里是没有自己的。
所以,我们需要知道自己的 id 信息在哪里获取。
UPDATE-2022-02-06:聊天文件是以聊天对象的 md5 值作为数据库名存储的,尽管在聊天记录中基于你和对象的微信 id 使用了一个字段表示聊天方向,但同时还有另外一个整型字段标志着是否是自己,所以尽管在联系人数据库中找不到自己的 id,但不影响对聊天记录中聊天方向的识别。
TODO: get image from xml
要遍历本地找!
sample
<!-- StrRes1 -->
<?xml version="1.0"?>\n<msg>\n\t<img aeskey="252260f7cd231a2ee75e997483fdbe26" encryver="0" cdnthumbaeskey="252260f7cd231a2ee75e997483fdbe26" cdnthumburl="3059020100045230500201000204d3e741cc02030f5bd102041be0cdcb020461fd7c48042b777875706c6f61645f777869645f636b3835787570386231626a32315f3335395f313634343030323337330204011d0a020201000400" cdnthumblength="2906" cdnthumbheight="120" cdnthumbwidth="55" cdnmidheight="0" cdnmidwidth="0" cdnhdheight="0" cdnhdwidth="0" cdnmidimgurl="3059020100045230500201000204d3e741cc02030f5bd102041be0cdcb020461fd7c48042b777875706c6f61645f777869645f636b3835787570386231626a32315f3335395f313634343030323337330204011d0a020201000400" length="1" md5="ac0d0d7ae1c546233d2dd8bdfbaa9d37" hevc_mid_size="77982" />\n</msg>\n
<!-- messageType -->
<msgsource>\n\t<bizflag>0</bizflag>\n\t<sec_msg_node>\n\t\t<uuid>e78ea49721c227614ead30b94f1dea68_</uuid>\n\t</sec_msg_node>\n\t<signature>v1_IC/iNhD5</signature>\n</msgsource>\n
ref
- windows version: 微信 hook 收到的图片消息怎么转换成图片呢_精易论坛
py-sqlcipher instruction
core ref
compile
编译步骤永远都是最烦的哎,不过还好都顺利通过了。
首先是下载源代码。
git clone https://github.com/rigglemania/pysqlcipher3
cd pysqlcipher3
其次是编译,有两种方案。
由于我现在系统中已经静态编译过 sqlcipher
已经有了 libsqlcipher
,所以我直接python setup.py install
就能成功。
find /usr/local/lib -name libsqlcipher.a
# output: /usr/local/lib/libsqlcipher.a
否则的话,我需要把在 sqlcipher
动态编译产生的 sqlite.[ch]
文件都拷贝到当前目录下。
再编译python setup.py build_amalgamation
又会发现src/python3/connection.h
报错找不到sqlcipher.h
了。
所以我们再……把 amalgamation
文件夹拷贝到 src/python3/
下,并重命名为sqlcipher
……(真忙啊……)
然后编译:
python setup.py build_amalgamation
python setup.py install
成功通过!
这样,你才能在 python 中使用 from pysqlcipher3 import dbapi2 as sqlite
。
测试是否有 pysqlcipher
:
connection
如果是已解密/未加密的数据库,则使用 sqlite3
或者 sqlcipher
皆可。d
但如果是加密的数据库,则必须使用 sqlcipher
进入解密。
以下皆以 sqlcipher
演示。
命令行版:
# 一句话搞定
sqlcipher DB/PATH
-- 验证
sqlite> PRAGMA key = "XXXX";
sqlite> PRAGMA cipher_compatibility = 3;
-- 测试
sqlite> .tables
python 版:
# Python 3.9.10
from pysqlcipher3 import dbapi2 as sqlite
from pysqlcipher3.dbapi2 import Connection
def auth_db(ddb_path: str, db_key: str) -> Connection:
logger.info({"dp_path": db_path})
conn = sqlite.connect(db_path)
conn.execute(f'PRAGMA key = "{db_key}";')
conn.execute(f"PRAGMA cipher_compatibility = 3;")
conn.commit()
logger.info(f"authenticated {db_file}")
return conn
table
list all the tables
If you are using pure sqlite/sqlcipher
, then using .tables
can list all the tables. However, it won't in the py program.
In programme, I need to using the following:
SELECT name FROM sqlite_master WHERE type = "table"
And the python may be:
tables = list(c.execute('SELECT name FROM sqlite_master WHERE type = "table"'))
And the sample result of tx-contact table is:
ref
list the columns of table (get table schema)
In sql, we can use:
-- to list all the tables in the database:
.tables
-- to show the schema for a given tablename:
.schema tablename
Otherwise:
PRAGMA table_info(table_name);
And to get column names in py:
columns = list(i[1] for i in conn.execute(f"PRAGMA table_info({table_name})"))
ref
format rows display
-- to show current configuration
.show
-- to show rows of columns
.headers ON
.mode columns
.nullvalue -
ref
How to properly format sqlite shell output? - Database Administrators Stack Exchange
How to properly format sqlite shell output? - Database Administrators Stack Exchange
sqlite - How to get a list of column names on Sqlite3 database? - Stack Overflow
list rows in one table
SELECT * from XXXTABLE
-- limit rows, skip/offset rows
SELECT * FROM table LIMIT -1 OFFSET 10
sample
ref
extended
how to know my openssl version/info
$ openssl version -a
LibreSSL 2.8.3
built on: date not available
platform: information not available
options: bn(64,64) rc4(16x,int) des(idx,cisc,16,int) blowfish(idx)
compiler: information not available
OPENSSLDIR: "/private/etc/ssl"
the OPENSSLDIR
is the config info for openssl other than the src files.
$ tree /private/etc/ssl
/private/etc/ssl
├── cert.pem
├── certs
├── openssl.cnf
└── x509v3.cnf
1 directory, 3 files
And as mentioned from Mac 终端使用 Sqlcipher 加解密基础过程详解_Martin.Mu `s Special Column-CSDN 博客_mac sqlcipher, the built-in openssl
on MacOS may not be suitable for our project target.
ref
bugfix: error: C compiler cannot create executables
ref
一个 mac 用户碰到了这个问题,然后在 github 询问:Installation on MacOS Catalina, C compiler cannot create executables · Issue #378 · sqlcipher/sqlcipher
上个用户被开发者劝退,说来这里问,但是这里没有得到回复😢:SQLCipher Installation on MacOS Catalina, C compiler cannot create executables - SQLCipher - Zetetic Community Discussion
这里看起来讨论的更热烈些,但和
sqlcipher
无关: command line - how to fix configure: error: C compiler cannot create executables - Ask Ubuntu