如果您希望使用全密态功能对数据库表中的被保护数据列进行加密,并且使用Go应用程序访问数据库,可以使用全密态客户端驱动程序alibabacloud-encdb-mysql-go-client接入全密态数据库。本文介绍如何通过Go驱动访问全密态数据库。
在持有用户密钥的情况下,alibabacloud-encdb-mysql-go-client能够自动完成密文数据的解密并返回明文数据,过程对应用透明,应用程序只需配置几行代码就可以接入全密态数据库,降低了使用全密态功能的成本。
前提条件
已开通全密态PolarMySQL功能,并按照实际需求配置了加密规则。开通全密态PolarMySQL功能的具体操作步骤请参见如何开通全密态PolarMySQL功能。
已获取加密数据库的连接信息。如域名(host)、端口(port)、数据库名(dbname)、用户名(username)和密码(password)等。
已部署Go程序,且Go版本需为1.18或以上。
操作步骤
获取全密态数据库Go驱动
go get github.com/aliyun/alibabacloud-encdb-mysql-go-client@latest
alibabacloud-encdb-mysql-go-client全面兼容社区版的GoLang MySQL Driver,支持标准GoLang的database/sql/driver接口,业务侧可实现零改造接入。
驱动已开源在GitHub,请参见https://github.com/aliyun/alibabacloud-encdb-mysql-go-client。
通过全密态客户端查询数据
您可以像使用GoLang MySQL Driver一样使用alibabacloud-encdb-mysql-go-client,但需要预先配置MEK(主密钥)和ENC_ALGO(加密算法)参数。PolarDB支持在URL链接中嵌入参数,方法如下:
mek := ...
encAlgo := ...
db, err := sql.Open("encmysql", "<username>:<password>@tcp(<hostname>:<port>)/<dbname>?MEK=<mek>&ENC_ALGO=<encAlgo>")
if err != nil {
panic(err)
}
在URL中配置多个参数时,多个参数之间使用
&
进行拼接。MEK在本地客户端上进行处理,并以安全的方式(信封加密)分发到服务器端,始终保证MEK不泄露。
MEK和encAlgo的说明及其示例见下表:
参数 | 说明 | 示例 |
MEK | 用户主密钥,由用户自定义指定。 常见的生成方法:密码生成工具(如openssl、openssl rand -hex 16)、编程语言中的random函数或者从第三方密钥管理服务(KMS)获取。 取值范围:长度为16个字节的十六进制字符串,且总长度为32个字符。 重要 用户主密钥是访问加密数据的根凭据,出于安全考虑,全密态数据库不持有并管理用户的主密钥,也不提供用户主密钥的生成和备份服务,您需要自行生成用户主密钥。一旦您丢失密钥,将无法再访问已有的数据。因此,建议您妥善备份用户主密钥。 | 00112233445566778899aabbccddeeff |
ENC_ALGO | 被保护数据使用的加密算法。目前支持AES(国际算法)和
说明 AES_128_ECB和SM4_128_ECB加密算法安全性较弱,请谨慎使用。 | SM4_128_CBC |
示例
该示例以新建demo项目go mod init demo为例,来介绍使用alibabacloud-encdb-mysql-go-client的方法。
package main
import (
"database/sql"
"fmt"
_ "github.com/aliyun/alibabacloud-encdb-mysql-go-client"
)
func main() {
db, err := sql.Open("encmysql", "<username>:<password>@tcp(<hostname>:<port>)/<dbname>?MEK=00112233445566778899aabbccddeeff&ENC_ALGO=SM4_128_CBC")
if err != nil {
panic(err)
}
_, err = db.Exec("DROP TABLE IF EXISTS test")
if err != nil {
panic(err)
}
_, err = db.Exec(`create table test(a int, b text, c float)`)
if err != nil {
panic(err)
}
_, err = db.Exec(`insert into test set a = 0, b = 'test', c = 0.0`)
if err != nil {
panic(err)
}
rows, err := db.Query("SELECT * FROM test")
rows.Next()
var a int
var b string
var c float32
err = rows.Scan(&a, &b, &c)
fmt.Printf("read data: %d %s %f\n", a, b, c)
}
实际执行过程中,请将示例中的域名(hostname)、端口(port)、数据库名(dbname)、用户名(username)和密码(password)等连接信息更换为实际的集群信息。调用上述代码后,系统返回类似如下解密后的结果信息:
read data: 0 test 0.000000