"Invalid use of a side-effecting operator 'OPEN SYMMETRIC KEY' within a function." error while opening a symmetric key

8.1k views Asked by At

I am trying to open symmetric key inside two functions. Like this:

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

But I am getting this error:

Invalid use of a side-effecting operator 'OPEN SYMMETRIC KEY' within a function.

Why this is happening?

2

There are 2 answers

2
James Z On BEST ANSWER

There are several things you can do inside a procedure but can't do inside a function. Based on Ben Cull's blog, you can get around this limitation by creating a procedure that handles opening the keys and call that before using the function.

The procedure:

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

Then just call this before calling the functions.

3
gotqn On

Actually, you can do this in function without opening the symmetric key using the DECRYPTBYKEYAUTOCERT function:

Decrypts by using a symmetric key that is automatically decrypted with a certificate.

The following example demonstrates this:

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;