作者:Mike Frank 译:徐轶韬
仅用于通过应用程序使用解密/加密
以下是一个示例,演示应用程序使用公钥进行非对称加密数据。在MySQL 8.0.19中,添加了支持Keyring技术的SECRET密钥类型。使用此技术,用户可以使用以下方法安全地管理自己的密钥:
Oasis KMIP协议实现:
Oracle Key Vault
Gemalto KeySecure
Thales Vormetric Key Management Server
Fornetix Key Orchestration
New! Townsend Alliance Key Manager
其他用于密钥管理的API:
使用自己的密钥– 加密密钥文件
Hashicorp Vault
更多
先决条件
MySQL企业版8.0.19或更高版本
1 | select @@version; |
演示开始
以管理员身份(以admin身份运行示例– root@localhost)安装MySQL Keyring
检查一下
1 | SELECT PLUGIN_NAME, PLUGIN_STATUS FROM INFORMATION_SCHEMA.PLUGINS WHERE PLUGIN_NAME LIKE 'keyring%'; |
下一步,安装MySQL Keyring UDF
12345678910111213 | INSTALL PLUGIN keyring_udf SONAME 'keyring_udf.so';CREATE FUNCTION keyring_key_generate RETURNS INTEGERSONAME 'keyring_udf.so';CREATE FUNCTION keyring_key_fetch RETURNS STRINGSONAME 'keyring_udf.so';CREATE FUNCTION keyring_key_length_fetch RETURNS INTEGERSONAME 'keyring_udf.so';CREATE FUNCTION keyring_key_type_fetch RETURNS STRINGSONAME 'keyring_udf.so';CREATE FUNCTION keyring_key_store RETURNS INTEGERSONAME 'keyring_udf.so';CREATE FUNCTION keyring_key_remove RETURNS INTEGERSONAME 'keyring_udf.so'; |
安装MySQL企业版加密
123456789101112131415161718 | CREATE FUNCTION asymmetric_decryptRETURNS STRING SONAME 'openssl_udf.so';CREATE FUNCTION asymmetric_deriveRETURNS STRING SONAME 'openssl_udf.so';CREATE FUNCTION asymmetric_encryptRETURNS STRING SONAME 'openssl_udf.so';CREATE FUNCTION asymmetric_signRETURNS STRING SONAME 'openssl_udf.so';CREATE FUNCTION asymmetric_verifyRETURNS INTEGER SONAME 'openssl_udf.so';CREATE FUNCTION create_asymmetric_priv_keyRETURNS STRING SONAME 'openssl_udf.so';CREATE FUNCTION create_asymmetric_pub_keyRETURNS STRING SONAME 'openssl_udf.so';CREATE FUNCTION create_dh_parametersRETURNS STRING SONAME 'openssl_udf.so';CREATE FUNCTION create_digestRETURNS STRING SONAME 'openssl_udf.so'; |
现在可以创建一个示例–在这种情况下,我们要
通过推入keyring 来保护私钥
如果您丢失了私钥–您将丢失所有加密数据。
如果密钥被盗–小偷可以读取您的敏感数据。
客户端应用程序的MySQL用户只能使用公钥加密敏感数据
另一个用户可以使用私钥解密该数据
创建用于存储敏感“秘密”数据的表
已经准备好了,让我们看一下这个例子:
123 | CREATE TABLE `secretdb`.`secrets_table`(`secid` INT NOT NULL, `secrets_tablecol` VARBINARY(3000) NOT NULL); |
创建私有PEM key并将其存储在MySQL keyring
123 | SELECT keyring_key_store('MySecret', 'SECRET',create_asymmetric_priv_key('RSA', 2048)); |
查看一下
1 | select keyring_key_fetch('MySecret'); |
创建一个函数,允许应用程序用户获取公钥并加密“秘密”。
在这种情况下,用户无法运行keyring_key_fetch(他们没有权限),因此,该函数将SQL SECURITY作为DEFINER(在本例中为root)运行。此函数将仅返回公钥(从keyring的私钥中提取出来)。
123456 | CREATE DEFINER = 'root'@'localhost' FUNCTION `secretdb`.`secdb_public_key`() RETURNS TEXT(500) deterministicSQL SECURITY DEFINERRETURN RTRIM(CREATE_ASYMMETRIC_PUB_KEY('RSA',keyring_key_fetch('MySecret'))); |
尝试一下
1 | select `secretdb`.`secdb_public_key`(); |
创建应用程序的MySQL用户,并对表和函数进行访问授权。
12 | CREATE USER 'appuser'@'%' IDENTIFIED BY <password>;GRANT USAGE ON *.* TO `appuser`@`%`; |
现在–试试看–以该用户身份登录
获取公钥
1 | select `secretdb`.`secdb_public_key`() into @pubk; GRANT SELECT, INSERT ON `secretdb`.* TO `appuser`@`%`'; GRANT EXECUTE ON FUNCTION `secretdb`.`secdb_public_key` TO 'appuser`@'%'; |
接下来,让我们创建一个“秘密”。
1 | SET @secretphrase='Sooo very secret 1'; |
定义密钥长度和算法
1 | SET @key_len = 2048; SET @algo = 'RSA'; |
加密数据
1 | SET @enc_value = ASYMMETRIC_ENCRYPT(@algo, @secretphrase, @pubk); |
查看其加密
1 | select 'Encrypted secret ', @enc_value; |
插入表
1 | INSERT INTO `secretdb`.`secrets_table` (`secid`, `secrets_tablecol`) VALUES (1, @enc_value); |
再做另外一个秘密
1 | SET @secretphrase='Sooo very secret 2'; select @secretphrase; Set @enc_value = ASYMMETRIC_ENCRYPT(@algo, @secretphrase, @pubk); select 'Encrypted secret 2', @enc_value; |
1 | INSERT INTO `secretdb`.`secrets_table` (`secid`,`secrets_tablecol`) VALUES (2, @enc_value); |
查看加密的数据
1 | select * from `secretdb`.`secrets_table`; |
注意:没有私钥,appuser无法解密。
以root身份登录并解密数据
12 | select `secrets_table`.`secrets_tablecol` into @encrsecretphrase from `secretdb`.`secrets_table` where secid=2;select @encrsecretphrase; |
1 | select keyring_key_fetch('MySecret') into @privappprivpkey; select @privappprivpkey; Set @enc_pp = ASYMMETRIC_DECRYPT(@algo, @encrsecretphrase, @privappprivpkey); select 'Secret', @enc_pp; |
作为root用户,可以看到数据。
现在,我们要提供除root用户以外的其他用户对私钥的访问权限。
1 | CREATE DEFINER = 'root'@'localhost' FUNCTION `secretdb`.`secdb_private_key`() RETURNS TEXT(500) deterministic SQL SECURITY DEFINER RETURN rtrim(keyring_key_fetch('MySecret')); |
以root身份测试
1 | select `secretdb`.`secdb_private_key`(); |
让我们创建另一个用户-该用户也有权访问数据。
1234 | CREATE USER 'privuser'@'%' IDENTIFIED BY <password>;GRANT USAGE ON *.* TO 'privuser'@'%'; GRANT SELECT ON `secretdb`.* TO 'privuser'@'%';GRANT EXECUTE ON FUNCTION `secretdb`.`secdb_private_key` TO 'privuser'@'%'; |
测试访问
1 | select `secretdb`.`secdb_private_key`(); |
检索数据
1 | SET @algo = 'RSA'; select `secrets_table`.`secrets_tablecol` into @encrsecretphrase from `secretdb`.`secrets_table` where secid=2; |
看-它已经加密
select @encrsecretphrase;
让我们解密
获取私钥
1 | select secretdb.secdb_private_key() into @privappprivpkey; |
用私钥解密数据
1 | Set @enc_pp = ASYMMETRIC_DECRYPT(@algo, @encrsecretphrase, @privappprivpkey); |
查看“秘密”
1 | select 'The secret is', @enc_pp; |
演示结束。
常见问题
如果我想加密/解密应用程序中的数据怎么办?
您可以使用带有公共或私有密钥(PEM格式)的openssl或兼容库来实现。只要确保您以二进制形式插入/更新数据即可。
如果我的数据大于非对称加密可以处理的数据怎么办?
进行混合加密,您可以获得与公钥相同的好处。
由于现在支持SECRET,因此无需将密钥存储在安全性较低的表中-现在您可以将它们作为SECRET类型放置在更安全的keyring上。
展望未来
试试看,不会花很长时间。通过keyring,非对称加密,对称加密,权限和其他访问控制,解决数据安全性的方法还有多种多样的选择。
例如,用户只能将公钥存储在主服务器上,将私钥存储在只读从服务器上。私钥只能存在于应用程序中,不能存在于mysql keyring上。或者,可以编写一个具有用户权限的函数,该函数可以在拥有权限时解密,但根本不显示私钥。
如果您遇到安全挑战,请告诉我们。
与往常一样,感谢您使用MySQL。
欢迎关注个人公众号“MySQL解决方案工程师”