“在函数中无效地使用了副作用运算符'OPEN SYMMETRIC KEY'。” 打开对称密钥时出错

Ais*_*iva 4 sql-server security encryption-symmetric sql-server-2008 sql-server-2012

我试图在两个函数中打开对称密钥。像这样:

CREATE FUNCTION DECRYPTDATA 
(
    @CipherText NVARCHAR(MAX)
)
RETURNS NVARCHAR(MAX)
AS
BEGIN
    DECLARE @Result NVARCHAR(MAX)
    OPEN SYMMETRIC KEY MyKEY DECRYPTION BY CERTIFICATE MyCERT
    SELECT @Result = CONVERT(VARCHAR(MAX),DECRYPTBYKEY(@CipherText))
    RETURN @Result

END
GO
CREATE FUNCTION ENCRYPTDATA 
(
    @Text NVARCHAR(MAX)
)
RETURNS NVARCHAR(MAX)
AS
BEGIN
    DECLARE @Result NVARCHAR(MAX)
    OPEN SYMMETRIC KEY MyKEY DECRYPTION BY CERTIFICATE MyCERT
    SELECT @Result = ENCRYPTBYKEY(Key_GUID('MyKEY'),@Text)
    RETURN @Result

END
GO
Run Code Online (Sandbox Code Playgroud)

但我收到此错误:

在函数中无效使用副作用运算符“ OPEN SYMMETRIC KEY”。

为什么会这样呢?

got*_*tqn 6

实际上,您可以在函数中执行此操作而无需使用DECRYPTBYKEYAUTOCERT函数打开对称密钥:

通过使用对称密钥进行解密,该对称密钥随证书自动解密。

下面的示例演示了这一点:

CREATE MASTER KEY ENCRYPTION
BY PASSWORD = 'sm_long_password@'
GO

CREATE CERTIFICATE CERT_01
WITH SUBJECT = 'CERT_01'
GO

CREATE SYMMETRIC KEY SK_01
WITH ALGORITHM = AES_256 ENCRYPTION
BY CERTIFICATE CERT_01
GO

CREATE FUNCTION [dbo].[TEST] (@encryptedValue VARBINARY(256))
RETURNS NVARCHAR(128)
AS
BEGIN;
    RETURN CONVERT(NVARCHAR(128),DECRYPTBYKEYAUTOCERT(CERT_ID('CERT_01'), NULL, @encryptedValue));
END
GO


DECLARE @encryptedValue VARBINARY(256);


OPEN SYMMETRIC KEY SK_01 DECRYPTION
BY CERTIFICATE CERT_01

SET @encryptedValue = ENCRYPTBYKEY(KEY_GUID('SK_01'), N'Stack Overflow')

CLOSE SYMMETRIC KEY SK_01;


SELECT [dbo].[TEST] (@encryptedValue);


DROP FUNCTION [dbo].[TEST];
DROP SYMMETRIC KEY SK_01;
DROP CERTIFICATE CERT_01;
DROP MASTER KEY;
Run Code Online (Sandbox Code Playgroud)


Jam*_*s Z 5

有几件事可以在过程中执行,但不能在函数中执行。根据 Ben Cull 的博客,您可以通过创建一个处理打开按键的过程并在使用该函数之前调用该过程来解决此限制。

步骤:

CREATE PROCEDURE OpenKeys
AS
BEGIN
    SET NOCOUNT ON;

    BEGIN TRY
        OPEN SYMMETRIC KEY MyKEY
        DECRYPTION BY CERTIFICATE MyCERT
    END TRY
    BEGIN CATCH
        -- Handle non-existant key here
    END CATCH
END
Run Code Online (Sandbox Code Playgroud)

然后在调用函数之前调用它。