首页 > 解决方案 > MSSQL & ColdFusion 加密转换

问题描述

我能够使用 3DES(和其他算法)使用 ColdFusion 加密数据。我还能够使用 MSSQL 3DES ( encryptByPassPhrase) 和EncryptByKey.

是否可以使用 3DES(或任何算法)在 ColdFusion 中加密数据,然后在 MSSQL 中解密数据?同样,是否可以在 MSSQL 中加密数据然后在 ColdFusion 中解密数据?

伊恩。

标签: sql-servertsqlencryptioncoldfusioncfml

解决方案


这似乎应该是一个简单的问题,但正如我上面所说,加密很快就会变得非常复杂。

对于这种特定情况,我的简短回答是“可能不会”。encrypt()CF和 SQL 的ENCRYPTBYPASSPHRASE()工作方式有所不同。即使您使用相同的密码,它们也不会加密到该值。甚至ENCRYPTBYPASSPHRASE()在加密值时使用了一些魔法。这是一个非确定性函数,这意味着给定相同的输入,输出可能不同。示例:尝试运行ENCRYPTBYPASSPHRASE(N'secretkey',N'myEncryptedValue1')' 5 times. You will get 5 different values.DECRYPTBYPASSPHRASE()` 足够聪明,可以知道 SQL Server 的密钥派生和加密方法,因此它能够解密给定正确密钥的值。

这里有几点需要注意:

1)ENCRYPTBYPASSPHRASE()返回一个varbinary(8000)数据类型。并且DECRYPTBYPASSPHRASE()还会返回一个varbinary(8000). 要获得可读值,您必须将值CONVERT()CAST()返回到nvarchar().

2)ENCRYPTBYPASSPHRASE()只接受char,binary以及它们的Nvar类型。因此,如果要加密任何其他类型,则必须将cast/convert其加密为二进制。

3) 这使用 3DES,它速度慢且不如“较新”的 AES 安全。DES 是不安全的,3DES 本质上就是 DES 运行 3 次。有更好的加密算法可用。而且由于 3DES 将在 SQL2016 之后被弃用,我猜它ENCRYPT/DECRYPTBYPASSPHRASE()也将被弃用或更改。此外,AES 虽然相当安全,但已经有将近 20 年的历史了。

4)ENCRYPTBYPASSPHRASE()通过非公开密钥派生函数运行其密码以生成 128 位密钥。这是我认为如果使用ENCRYPTBYPASSPHRASE(). 根本没有可靠的方法来重新生成用于加密值的实际密钥。

我进行了一些测试来演示我上面所说的一些内容:

db<>在这里摆弄

CREATE TABLE t1 (enc varbinary(8000));

DECLARE @secretKey Nvarchar(20) = N'secretkey' ;

INSERT INTO t1 
VALUES
    (ENCRYPTBYPASSPHRASE(@secretKey, N'myEncryptedValue1'))
  , (ENCRYPTBYPASSPHRASE(@secretKey, N'myEncryptedValue2'))
  , (ENCRYPTBYPASSPHRASE(@secretKey, N'myEncryptedValue3'))
  , (ENCRYPTBYPASSPHRASE(@secretKey, N'myEncryptedValue4'))
;

让我们解密我们输入的内容。

SELECT CONVERT(nvarchar(4000),DECRYPTBYPASSPHRASE(N'secretkey',enc)) FROM t1 ;
| (无列名) |
| :---------------- |
| 我的加密值1 |
| 我的加密值2 |
| 我的加密值3 |
| 我的加密值4 |

使用DECRYPTBYPASSPHRASE(),我们可以解密不同 SQL Server 上的值。它不依赖服务器的证书来进行加密。

现在让我们证明它EncryptByPassphrase()是非确定性的。

TRUNCATE TABLE t1;

/* Are we empty? */
SELECT * FROM t1 ; 

|       enc        |
| No rows returned |

/* Insert the same value multiple times, encrypted. */
INSERT INTO t1 
VALUES 
    ( ENCRYPTBYPASSPHRASE('secretkey','myEncryptedValue1') ) 
  , ( ENCRYPTBYPASSPHRASE('secretkey','myEncryptedValue1') )
  , ( ENCRYPTBYPASSPHRASE('secretkey','myEncryptedValue1') ) 
  , ( ENCRYPTBYPASSPHRASE('secretkey','myEncryptedValue1') ) 
  , ( ENCRYPTBYPASSPHRASE('secretkey','myEncryptedValue1') )
;

/* Do all rows encrypt to the same value? */
SELECT * FROM t1 ; 
| 编码 |
| :------------------------------------------------ ---------------------------------------------------- |
| 0x01000000FE4E975E32AF37B6EB2E497C76C3404ED8C06E1264DCE96C1753B89812636BFE28581DA788046994 |
| 0x010000008A684062BFF1A63FC86FFDE508CA30A5130BD51459DAFD9B18CF5DD0E7775D90BC80574953C26161 |
| 0x01000000084828F7D3E2053D9E13B45B9C42A34242F6ECF5D6A9DC934EA9EE10F3BD2CFB61AA1C9EBC8DB97E |
| 0x0100000083A4E21C5F5BD8CBE65CA83DEB4A46F58D1F74768760EC28C3836E1F285E65E289A6EFB6428BD738 |
| 0x01000000DFEA8A52F63726D93E4561A19CEEFD427460E0B8617BE6633210DFFF43DD4DD083DF4CF4CB85F129 |

ENCRYPTBYPASSPHRASE()这是多次加密的相同值,但会产生 5 个不同的值。这表明 SQL 的幕后发生了一些神奇的事情。我们无法在 ColdFusion 中解密该值,因为我们不知道在加密发生之前发生的密钥派生。

现在,所有这一切,我对你的问题的更长的回答“你能在 CF 和 SQL 之间共享加密吗?” 将是“视情况而定”。

显然,使用 SQLENCRYPT/DECRYPTBYPASSPHRASE()不适用于 CF,因为没有真正的方法可以可靠地知道用于加密值的派生密钥。但是,有很多方法可以剥去加密猫的皮肤。同样,您需要自己回答的主要问题是“我要保护什么类型的数据?”。这将告诉您最终需要哪种类型的加密。

由于我已经使用了这么多字符,只是简单地触及了您正在使用的一种技术中的几个功能,我认为这又回到了我最初的观点,即加密很快就会变得非常复杂。


推荐阅读