一、功能简介[yejrdb160 gt-checksum]$ cat docs/gt-checksum-v4.0.0-dsn-encrypt-article.mdgt-checksum v4.0.0 新功能解读系列文章5DSN 密文保护——连接串密码不再明文裸奔在数据库校验和修复工具中连接串几乎是最敏感的配置之一。过去为了使用方便很多配置文件会直接写入数据库明文密码。gt-checksum v4.0.0 起srcDSN / dstDSN 中的 password 必须使用 ENC[…] 密文并新增独立工具 gt-dsn-crypt 生成 32 字节 base64 key 与 AES-256-GCM 密文让连接串密码保护从“建议项”变成“强约束”。一、功能简介v4.0.0 新增连接串密码加密能力核心变化可以概括为三点能力 说明ENC[…] 密文格式 srcDSN / dstDSN 中的 password 必须使用 ENC[…] 密文gt-dsn-crypt 工具 独立生成 key、加密 password、解密校验密文统一日志脱敏 gt-checksum、repairDB、连接池日志均不会完整输出明文 password 或密文新增工具gt-dsn-cryptgt-dsn-crypt 提供三个子命令子命令 作用gen-key 生成 32 字节随机 key并以 base64 输出encrypt 使用 key 将明文 password 加密为 ENC[…] 密文decrypt 使用 key 解密 ENC[…]用于校验密文是否正确典型使用方式1. 生成 32 字节 base64 keyKEY$(gt-dsn-crypt gen-key)2. 推荐从文件读取 password避免明文进入 shell historyprintf ‘%s’ ‘数据库密码’ ./password.txt3. 生成 ENC[…] 密文GT_CHECKSUM_DSN_KEY“$KEY” gt-dsn-crypt encrypt --password-file ./password.txt4. 启动 gt-checksum 时提供同一个 keyGT_CHECKSUM_DSN_KEY“$KEY” gt-checksum -c ./gc.conf配置文件中的 DSN 变为srcDSNmysql|user:ENC[v1:aes256gcm:default:…:…]tcp(src-host:3306)/information_schema?charsetutf8mb4dstDSNmysql|user:ENC[v1:aes256gcm:default:…:…]tcp(dst-host:3306)/information_schema?charsetutf8mb4二、功能作用及使用场景深入解读2.1 为什么要强制加密 DSN password在生产环境中明文数据库密码的风险远比想象中更常见场景一配置文件泄露gc.conf 通常会被放在运维目录、部署目录或自动化平台中。一旦目录权限配置不当明文数据库密码就可能被非授权用户读取。场景二日志与报错泄露工具启动失败、参数校验失败、连接池初始化失败时如果直接打印 DSN明文 password 可能进入终端日志、CI 日志、工单截图或监控采集系统。场景三多人协作与审计迁移项目通常涉及 DBA、研发、运维、测试多角色协作。配置文件被多人传递时明文密码会在聊天工具、邮件、文档中扩散后续很难追踪和回收。场景四临时文件与历史命令残留即使最终配置文件被删除明文密码仍可能残留在 shell history、备份文件、编辑器 swap 文件中。加密后即使密文泄露没有 key 也无法直接还原 password。因此v4.0.0 不再只是“建议不要写明文密码”而是在启动阶段直接校验DSN password 不是 ENC[…]程序 fail-fast 退出。2.2 ENC[…] 密文格式是什么v4.0.0 使用统一的密文格式ENC[v1:aes256gcm::nonce_b64url:ciphertext_b64url]各字段含义如下字段 说明v1 密文格式版本aes256gcm 加密算法AES-256-GCMkey id默认 default为后续密钥轮换预留随机 nonce使用 base64 URL-safe 编码 密文和认证标签使用 base64 URL-safe 编码示例ENC[v1:aes256gcm:default:REPLACE_NONCE:REPLACE_CIPHERTEXT]需要注意的是只加密 password 片段不会加密 host、port、库名、charset、SSL 参数等连接配置信息。例如加密前v4.0.0 起不再支持srcDSNmysql|user:plain_passwordtcp(src-host:3306)/information_schema?charsetutf8mb4加密后srcDSNmysql|user:ENC[v1:aes256gcm:default:…:…]tcp(src-host:3306)/information_schema?charsetutf8mb4这种设计兼顾了安全性和可运维性密码被保护起来但连接目标、库名和参数仍然可见便于排查配置问题。2.3 AES-256-GCM同时保证保密性和完整性gt-dsn-crypt 使用 Go 标准库中的 AES-GCM 实现block, _ : aes.NewCipher(key)gcm, _ : cipher.NewGCM(block)nonce : make([]byte, gcm.NonceSize())rand.Read(nonce)ciphertext : gcm.Seal(nil, nonce, []byte(password), nil)这里有几个关键点key 必须是 32 字节对应 AES-256。每次加密都会生成随机 nonce同一个 password 用同一个 key 加密两次也会得到不同的 ENC[…] 密文。GCM 自带认证标签解密时会校验密文是否被篡改。如果 key 错误或密文被修改会返回解密失败而不是输出错误的 password。这意味着 ENC[…] 不只是“混淆字符串”而是具备认证加密能力的密文格式。2.4 key 从哪里来v4.0.0 的 key 管理遵循两个原则不内置默认 key不从配置文件读取 key。key 来源只有两种来源 优先级 说明–key 最高 命令行参数覆盖环境变量GT_CHECKSUM_DSN_KEY 次高 未指定 --key 时读取该环境变量示例使用环境变量GT_CHECKSUM_DSN_KEY“$KEY” gt-checksum -c ./gc.conf使用 --key 覆盖环境变量gt-checksum -c ./gc.conf --key “$KEY”repairDB 和 gt-dsn-crypt 也使用同样的 key 机制repairDB 使用环境变量GT_CHECKSUM_DSN_KEY“$KEY” repairDB -conf ./gc.conf ./fixsqlrepairDB 使用 --keyrepairDB -conf ./gc.conf --key “$KEY” ./fixsqlgt-dsn-crypt encrypt 使用 --keygt-dsn-crypt encrypt --key “$KEY” --password-file ./password.txtv4.0.0 不支持密钥文件也不支持把 key 写在 gc.conf 中。这是为了避免“密码加密了但解密 key 又和配置文件放在一起”的伪安全。2.5 启动阶段 fail-fast明文密码直接拒绝gt-checksum 在读取配置时会立即解析 srcDSN / dstDSN并调用统一的连接串解析逻辑要求连接串中 必须使用密文。因此password 是 ENC[…]加载 key 并解密password 是明文直接报错退出password 为空直接报错退出key 缺失或 key 长度不是 32 字节直接报错退出密文格式错误、版本不支持、认证失败直接报错退出这种 fail-fast 设计可以把风险拦截在任务启动阶段避免校验或修复运行到一半才发现连接串不可用。2.6 MySQL 与 Oracle DSN 都支持v4.0.0 的连接串加密不只支持 MySQL-family也支持 Oracle。MySQL-familysrcDSNmysql|user:ENC[v1:aes256gcm:default:…:…]tcp(src-host:3306)/information_schema?charsetutf8mb4dstDSNmysql|user:ENC[v1:aes256gcm:default:…:…]tcp(dst-host:3306)/information_schema?charsetutf8mb4Percona Server、GreatSQL、MariaDB 等 MySQL-family 数据源同样使用 mysql| 驱动前缀。Oracle legacy DSNsrcDSNoracle|scott/ENC[v1:aes256gcm:default:…:…]ora-host:1521/orclpdb1Oracle godror key-value DSNsrcDSNoracle|user“scott” password“ENC[v1:aes256gcm:default:…:…]” connectString“ora-host:1521/orclpdb1”Oracle legacy 格式中解密后的 password 会按路径片段做转义避免 / 等特殊字符破坏 user/passwordhost 的结构key-value 格式则会保留或补齐引号避免空格和特殊字符导致解析错误。2.7 日志统一脱敏不让密文变成另一种泄露只加密配置文件还不够。如果程序启动后把解密后的 DSN 打印到日志里风险仍然存在。v4.0.0 对 gt-checksum、repairDB、MySQL/Oracle 连接池日志做了统一脱敏处理mysql|user:tcp(src-host:3306)/information_schema?charsetutf8mb4oracle|scott/ora-host:1521/orclpdb1oracle|user“scott” password“******” connectString“ora-host:1521/orclpdb1”也就是说无论 DSN 中原本是明文、ENC[…] 密文还是运行时已解密后的真实 password日志里都会被替换为 ******。三、功能使用演示3.1 生成 key$ gt-dsn-crypt gen-keyIs7oYfqpCNZc6mD8kKY/yFevgYrjU//y4SM2K40yzM4$ export GT_CHECKSUM_DSN_KEY“Is7oYfqpCNZc6mD8kKY/yFevgYrjU//y4SM2K40yzM4”这是一个 base64 编码后的 32 字节随机 key。生产环境建议把它放入安全的密钥管理系统或通过环境变量注入任务进程。3.2 生成 password 密文推荐把数据库 password 写入临时文件再使用 --password-file 加密$ printf ‘%s’ ‘GreatSQL2026!’ ./password.txt$ GT_CHECKSUM_DSN_KEY“$KEY” gt-dsn-crypt encrypt --password-file ./password.txtENC[v1:aes256gcm:default:Qk1…:8dF…]也可以直接使用 --passwordgt-dsn-crypt encrypt --key “$KEY” --password ‘GreatSQL2026!’但这种方式可能被 shell history 记录生产环境不推荐。3.3 写入 gc.confsrcDSNmysql|user:ENC[v1:aes256gcm:default:Qk1…:8dF…]tcp(10.0.0.1:3306)/information_schema?charsetutf8mb4dstDSNmysql|user:ENC[v1:aes256gcm:default:9mA…:rK2…]tcp(10.0.0.2:3306)/information_schema?charsetutf8mb4tablesdb.*checkObjectdatadatafixfile注意源端和目标端可以使用同一个 key 生成密文也可以通过 kid 记录不同的 key id。但运行时当前实现需要提供能解开配置中密文的 key。3.4 启动 gt-checksum$ GT_CHECKSUM_DSN_KEY“$KEY” gt-checksum -c ./gc.confInitializing gt-checksumReading configuration filesOpening log filesChecking configuration optionsgt-checksum: Starting table checks…或者使用 --key$ gt-checksum -c ./gc.conf --key “$KEY”3.5 repairDB 使用密文 dstDSNrepairDB 只连接目标端因此只读取并解密 dstDSNdstDSNmysql|user:ENC[v1:aes256gcm:default:9mA…:rK2…]tcp(10.0.0.2:3306)/information_schema?charsetutf8mb4fixFileDir./fixsql执行修复$ GT_CHECKSUM_DSN_KEY“$KEY” repairDB -conf ./gc.conf ./fixsql[REPAIR] Processing: table.db.orders.INSERT-1.sql … OK…3.6 解密校验如果需要确认某个密文对应的 password 是否正确可以使用 decrypt$ GT_CHECKSUM_DSN_KEY“$KEY” gt-dsn-crypt decrypt --ciphertext ‘ENC[v1:aes256gcm:default:Qk1…:8dF…]’GreatSQL2026!解密命令建议仅在本地临时验证时使用避免把明文输出到共享终端、CI 日志或工单系统。3.7 明文 password 报错示例如果配置文件仍然使用明文 passwordsrcDSNmysql|user:plain_passwordtcp(10.0.0.1:3306)/information_schema?charsetutf8mb4启动时会直接失败$ gt-checksum -c ./gc.confgt-checksum: invalid srcDSN password: dsn password must use ENC[…] ciphertext如果没有提供 key$ gt-checksum -c ./gc.confgt-checksum: invalid srcDSN password: dsn encryption key is required四、最佳实践及使用约束4.1 最佳实践生产环境统一使用 --password-file 加密相比 --password–password-file 可以避免 password 进入 shell historyprintf ‘%s’ ‘数据库密码’ ./password.txtGT_CHECKSUM_DSN_KEY“$KEY” gt-dsn-crypt encrypt --password-file ./password.txtrm -f ./password.txt2. key 不要与 gc.conf 放在一起不要把 key 写入配置文件也不要把 key 文件和 gc.conf 放在同一目录打包传递。推荐使用CI/CD secretKubernetes Secret操作系统环境变量企业密钥管理系统3. 使用 --key 覆盖临时环境变量当同一台机器上需要执行多个不同项目的校验任务时可以用 --key 显式指定当前任务的 key避免误用环境变量中的旧 keygt-checksum -c ./gc-prod.conf --key “$PROD_DSN_KEY”4. 日志可以共享配置和 key 不能共享v4.0.0 已经对 DSN 日志做了统一脱敏因此日志文件相对更安全。但配置文件中的 ENC[…] 密文和运行时 key 仍然应按敏感信息管理。定期轮换 key 和密文如果项目成员变更、配置文件曾经外发建议重新生成 key并重新生成 srcDSN / dstDSN 密文。ENC[…] 中的 kid 字段可用于记录 key id方便人工追踪密钥版本。配合 SSL 加密连接使用DSN 密文保护的是“静态配置文件中的 password”SSL 保护的是“运行时网络传输中的数据”。两者解决的问题不同生产环境建议同时启用srcDSNmysql|user:ENC[…]tcp(src-host:3306)/information_schema?charsetutf8mb4dstDSNmysql|user:ENC[…]tcp(dst-host:3306)/information_schema?charsetutf8mb4srcSslModeVERIFY_CAdstSslModeVERIFY_CA4.2 使用约束明文 password 不再兼容v4.0.0 起srcDSN / dstDSN 的 password 必须使用 ENC[…]。旧版本配置如果仍然使用明文 password需要先迁移为密文格式否则启动即失败。key 必须是 base64 编码后的 32 字节随机值gt-dsn-crypt gen-key 生成的 key 可以直接使用。如果手动生成 key必须保证 base64 解码后长度正好为 32 字节否则会报错dsn encryption key must be base64 encoded 32 bytes3. 不支持密钥文件工具不提供 --key-file 参数也不会从配置文件中读取 key。key 只能通过 --key 或 GT_CHECKSUM_DSN_KEY 提供。密文只保护 password不保护完整 DSNENC[…] 只加密 passwordhost、port、库名、charset、SSL 参数等仍然以明文保留在配置文件中。这是为了保留必要的可运维信息。如果连接目标本身也属于敏感信息需要通过配置文件权限和部署系统进行额外保护。key 丢失后无法恢复 passwordAES-256-GCM 是对称加密。没有正确 key无法解密 ENC[…]。因此 key 必须妥善备份和管理如果 key 丢失只能重新获取数据库 password 并重新生成密文。decrypt 命令会输出明文gt-dsn-crypt decrypt 是为了本地校验密文是否正确输出结果就是明文 password。不要在共享终端、CI pipeline、公开日志中执行该命令。五、总结gt-checksum v4.0.0 的 DSN 密文保护能力把连接串密码安全提升到了默认强制级别。配置文件中不再允许明文 password启动时必须通过 --key 或 GT_CHECKSUM_DSN_KEY 提供 32 字节 base64 key程序在内存中解密后连接数据库并对所有 DSN 日志输出统一脱敏。围绕这一能力v4.0.0 形成了一套完整闭环gt-dsn-crypt gen-key生成 32 字节随机 keygt-dsn-crypt encrypt生成 AES-256-GCM ENC[…] 密文gt-dsn-crypt decrypt本地解密校验gt-checksum --key / GT_CHECKSUM_DSN_KEY运行时解密 srcDSN / dstDSNrepairDB --key / GT_CHECKSUM_DSN_KEY运行时解密 dstDSN日志统一脱敏避免明文或密文再次泄露一句话总结srcDSNmysql|user:ENC[…]…让数据库密码不再出现在配置文件和日志里。