I have a scenario where i need to have literals(hard coded strings) inside proc used against \"Always Encrypted\" columns, Since this fails with the following error,
I found a work around for using hard coded strings in procedures.
Example:
Create table with encrypted column
CREATE TABLE [dbo].[Encrypted_nVarchar_256](
[SNo] [smallint] IDENTITY(-32768,1) NOT NULL,
[EncryptValue] [nvarchar](256) COLLATE Latin1_General_BIN2
ENCRYPTED WITH (COLUMN_ENCRYPTION_KEY = [CEK_key], ENCRYPTION_TYPE = Deterministic, ALGORITHM = 'AEAD_AES_256_CBC_HMAC_SHA_256') NULL,
[Value_Description] [nvarchar](256) NULL,
CONSTRAINT [Pk_Enc_nVar_256] PRIMARY KEY CLUSTERED
(
[SNo] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
Insert text into encrypted column the value that you would required to be used inside procedures.
DECLARE @EncryptValue nvarchar(256) ='';
INSERT INTO Encrypted_nVarchar_256(EncryptValue,[Value_Description]) VALUES(@EncryptValue,'Empty string')
DECLARE @EncryptValue1 nvarchar(256) ='Some string you would like to hard code';
INSERT INTO Encrypted_nVarchar_256(EncryptValue,[Value_Description]) VALUES(@EncryptValue1,'Your description')
--more rows as you need
GO
Now you could consume in stored procedure
CREATE PROCEDURE InsertProc
@Var1 nVarchar(20)
As
BEGIN
--Passing hard coded ''(Empty string) as insert value
INSERT INTO testTable(EncryptedCol1,EncryptedCol2,NonEncryptedCol)
SELECT TOP 1 EncryptValue,@Var1,"some string" FROM Encrypted_nVarchar_256 where Sno=-32768
--Comparing some hard coded string
SELECT * from testTable
where EncryptedCol1=(SELECT TOP 1 EncryptValue FROM Encrypted_nVarchar_256
where Sno=-32768)
--Using in functions
SELECT COALESCE(EncryptedCol1,(SELECT TOP 1 EncryptValue FROM Encrypted_nVarchar_256 where Sno=-32768)) as [new col name] from testable
END
Voila!!! now you could do anything with just a little twist.
The main purpose of Always Encrypted is to make it impossible for SQL Server (hence your DBAs) to decrypt your sensitive data. To achieve this SQL Server has abolutely no access to they encryption keys and can't encrypt and decrypt data. All encryption and decryption is performed by the client (your application, SSMS, etc.). Enable Parameterization for Always Encrypted is a feature of SSMS. When it is enabled (and you specify Column Encryption Setting=Enabled for your connection), SSMS will detect the declared variables in your script, convert it to parametrized query and executes this converted version of it. This way the parameter values will be encrypted on the client and SQL Server will not see their plain text values at all.
In your example, @Plaintext is not a variable declared in your script, but local variable for the stored procedure. So this code (the assigning of the value) will be performed in the SQL Server's engine itself, and since it doesn't has access to the encryption keys, it is simply impossible to encrypt the value. So you need to move this as input parameter for the store procedure too. In this case it will be tempting to give it a default value and omit it when calling the procedure, but the default value is something stored in the metadata and it is in plain (not encrypted). Someone have to encrypt it, and the only one who can do this is the client. Hence, you need to pass it from the client and not to make it a default value, i.e. it is not possible to use "hard-coded values" in the server.
If this is a major obstacle for you, probably Always Encrypted isn't the right technology for your case. If you use lets say column level encryption with certificates, you will be able to do all these things. But this defeats the main advantage of Always Encrypted - the inability your DBA to get access to your secrets.