Home > OS >  Encrypting and Decrypting String Using SQL's EncryptByPassPhrase
Encrypting and Decrypting String Using SQL's EncryptByPassPhrase

Time:05-12

I have a need to Encrypt text, transmit the encrypted text, and decrypt the text ... using SQL.

I tried EncryptByPassPhrase which returns a VARBINARY. I convert it to VARCHAR (for easier transmitting), and when I try to convert it back to VARBINARY, it fails. From what I can see, the CONVERT from VarBinary to VarChar, truncates the string, appears like the second half of the VarBinary value gets dropped when converting to VarChar. So when converting back from that VarChar value, it is incomplete and fails.

Here is sample code:

DECLARE @binEncryptedText VARBINARY(MAX) = EncryptByPassPhrase('Password', 'My Text')
DECLARE @strEncryptedText VARCHAR(MAX) = CONVERT(VARCHAR, @binEncryptedText, 2)

DECLARE @binDecryptedText VARBINARY(MAX) = CONVERT(VARBINARY, @strEncryptedText, 2)
DECLARE @strDecryptedText VARCHAR(MAX) = CONVERT(VARCHAR, DecryptByPassPhrase('Password', @binDecryptedText))

SELECT 1 As RowNumber,
       @binEncryptedText AS EncryptedBinary,
       @strEncryptedText AS EncryptedBinaryAsText
UNION
SELECT 2 As RowNumber,
       @binDecryptedText AS EncryptedBinary,
       @strDecryptedText AS EncryptedBinaryAsText

SQL Results

As you can see in the screenshot of my results above... In Row #1, the Binary that was converted to Text ... is shorter than the original Binary (truncated roughly halfway). So when converting that truncated text back to Binary, it fails to return the complete value ... which then causes the Decrypt to fail.

How can I get the encrypted text's VarBinary converted to "text" and then have the "text" converted back to the correct VarBinary value so it can be decrypted?

CodePudding user response:

MSSQL has a well hidden Base64 encoder and decoder - within the XML subsystem. Convert the encrypted varbinary to Base64 for transmission, it will become an ASCII string, transmit the string, then decode back to a varbinary. The encoder/decoder is an XPath function, so you need an XML context to run it, but you can provide a dummy one. So the code for encoding goes:

cast('' as xml).value('xs:base64Binary(sql:variable("@b"))', 'varchar(max)')

where @b is your varbinary.

To decode:

cast('' as xml).value('xs:base64Binary(sql:variable("@s"))', 'varbinary(max)')

where @s is the Base64 string.

It's kind of funky that the encoder and the decoder is the same function, but I guess it knows what to do by the datatype of the argument. I haven't used this technique extensively myself, but I've tried it and it worked as expected. MSSQL 2019.

You can also use xs:hexBinary to encode the binary data as hex. Base64 representation is smaller, though; 4 characters for 3 bytes vs. 2 for 1.

CodePudding user response:

So I actually ended up figuring out what my problem was. In SQL, some of my commands were "incomplete" ... in a manner of speaking.

DECLARE @binEncryptedText VARBINARY(MAX) = EncryptByPassPhrase('Password', 'My Text')
DECLARE @strEncryptedText VARCHAR(MAX) = CONVERT(VARCHAR(MAX), @binEncryptedText, 2)

DECLARE @binDecryptedText VARBINARY(MAX) = CONVERT(VARBINARY(MAX), @strEncryptedText, 2)
DECLARE @strDecryptedText VARCHAR(MAX) = CONVERT(VARCHAR(MAX), DecryptByPassPhrase('Password', @binDecryptedText))

SELECT 1 As RowNumber,
       @binEncryptedText AS EncryptedBinary,
       @strEncryptedText AS EncryptedBinaryAsText
UNION
SELECT 2 As RowNumber,
       @binDecryptedText AS EncryptedBinary,
       @strDecryptedText AS EncryptedBinaryAsText

As you can see in the code above, in the CONVERT statements ... I needed to add the additional "size" of the returning VARCHAR I was converting to. Previously my convert commands said ...

...CONVERT(VARCHAR, ...

... when they should have said ...

...CONVERT(VARCHAR(MAX), ...

Once I made that change, the returning HEX String was no longer being truncated.

  • Related