集成GoLang驱动

如果您希望使用全密态功能对数据库表中的被保护数据列进行加密,并且使用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
说明

通过全密态客户端查询数据

您可以像使用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(国际算法)和SM4(国密算法)两个大类,其中具体的算法有:

  • SM4_128_GCM(默认)

  • SM4_128_CTR

  • SM4_128_CBC

  • SM4_128_ECB(不推荐)

  • AES_128_GCM

  • AES_128_CTR

  • AES_128_CBC

  • AES_128_ECB(不推荐)

说明

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