go 如何直接打开加密的 sqlite3 db 文件

2021-12-30 12:02:25 +08:00
 CurChen

尝试过

都失败了

打开 db 代码如下:

	dbname := `***.db`
	key := "dd85344"
	dbnameWithDSN := dbname + fmt.Sprintf("?_pragma_key=%s&_pragma_cipher_page_size=4096", key)
	db, err := gorm.Open(sqlite.Open(dbnameWithDSN), &gorm.Config{})

也尝试过\

	dbname := `***.db`
	key := "dd85344"
	dbnameWithDSN := dbname + fmt.Sprintf("?_pragma_key=%s&_pragma_cipher_page_size=4096", key)
	db, _ := sql.Open("sqlite3", dbname)

密码肯定是对的,不过我这边的 key 是 7 位的,官方说的是必须为 32 字节十六进制编码
我觉得问题应该出现在这,但是我不知道该怎么下一步转换了

3603 次点击
所在节点    Go 编程语言
10 条回复
hemingway
2021-12-30 12:05:49 +08:00
```
_pragma_key=x'%s'
```
%s 前面有 x 你的没有,你改下试试
CurChen
2021-12-30 12:13:31 +08:00
@hemingway
db, err := sql.Open("sqlite3", fmt.Sprintf("%s?_pragma_key=x'%s'&_pragma_cipher_page_size=4096", dbname, key))
db, err := sql.Open("sqlite3", fmt.Sprintf("%s?_pragma_key=x%s&_pragma_cipher_page_size=4096", dbname, key))
db, err := sql.Open("sqlite3", fmt.Sprintf("%s?_pragma_key=%s&_pragma_cipher_page_size=4096", dbname, key))
都不行的
junnplus
2021-12-30 14:19:38 +08:00
你用的 v4 的包么?好像用 v4 没问题
junnplus
2021-12-30 14:24:42 +08:00
```
dbname = fmt.Sprintf("%s?_pragma_key=passphrase&_pragma_cipher_page_size=4096", dbname)
db, err := sql.Open("sqlite3", dbname)
if err != nil {
panic(err)
}
```
CurChen
2021-12-30 14:47:36 +08:00
@junnplus 是 v4 的包
go.mod
github.com/mutecomm/go-sqlcipher/v4 v4.4.2 // indirect

我觉得应该是 key 出的问题,不知道该怎么把 7 位字符的 key 转成官方要的 32 字节十六进制编码
junnplus
2021-12-30 14:53:22 +08:00
@CurChen 不需要转,你看我上面的代码,没问题的
Mitt
2021-12-30 14:56:45 +08:00
hex.EncodeToString([]byte("dd85344"))
Mitt
2021-12-30 14:58:58 +08:00
不对我看错了
CurChen
2021-12-30 15:24:51 +08:00
@junnplus
db, err := sql.Open("sqlite3", `xxx.db?_pragma_key=dd85344&_pragma_cipher_page_size=4096`)
if err != nil {
t.Fatal(err)
}
rows, err := db.Query("SELECT id,value FROM userinfo")
if err != nil {
t.Fatal(err)
}
最后的 err 会返回:file is not a database
CurChen
2021-12-30 16:35:38 +08:00
我使用 sqlcipher.exe 执行
```base
sqlcipher.exe F:\testdata\xxx.db
sqlite> PRAGMA key = 'dd85344';
sqlite> PRAGMA cipher_use_hmac = off;
sqlite> PRAGMA cipher_page_size = 1024;
sqlite> PRAGMA kdf_iter = 4000;
sqlite> .table
```
成功了

这是我的 golang 代码
```golang
import (
"database/sql"
"fmt"
"testing"

_ "github.com/mutecomm/go-sqlcipher/v4"
)

func TestDecrypt(t *testing.T) {
dbname := fmt.Sprintf("%s?_pragma_key=%s&_pragma_cipher_use_hmac=off&_pragma_cipher_page_size=1024&_pragma_kdf_iter=4000", `F:\testdata\xxx.db`, "dd85344")
db, err := sql.Open("sqlite3", dbname)
if err != nil {
panic(err)
}
_, err = db.Query("SELECT id,value FROM userinfo")
if err != nil {
panic(err)
}
}
```
最后的 error 会报错 : "file is not a database"

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/825252

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX