When calling EncryptByKey()
in SQL server you will get a bunch of bytes in return. This article from Microsoft describes the structure of these bytes.
If you pay close attention, it is even possible to work with this format outside of SQL server. Both decrypting and encrypting is possible, given that you can get the encryption key available outside of SQL Server. Using a HSM with the EKM integration is one way to do this, as SQL server has no native integration for exporting and importing keys.
Cryptographic message
Long story short:
- 16 bytes: key GUID
- x bytes: header
- x bytes: IV
- n bytes: ciphertext
Creating the ciphertext
The plaintext must be prepended with the following bytes:
- Magic number:
0x0DF0ADBA
. Decryption will fail if the plaintext does not start with this number. - Integrity bytes length:
0x0000
because we don’t use authentication in this example - Plaintext Length: litle endian 16-bit integer. 12 bytes of plaintext will give
0x0C00
- IntegrityBytes: nothing, we don’t use this in this example
The header will have these bytes: 0x0DF0ADBA00000C00
. The plaintext bytes follow immediately after it.
After these bytes, the padded plaintext follows. PKCS#5 padding seems to work just fine. The plaintext with header bytes is then fed into the AES-CBC cipher.