Recreate symmetric key of unknown CREATE SYMMETRIC KEY
I found that for each encryption of a symmetric key an entry in sys.key_encryptions
is present and at least for ENCRYPTION BY CERTIFICATE
-type entries I can use the certificate of the specified thumbprint
to decrypt the crypt_property
:
SELECT
SK.name,
SK.key_length,
SK.algorithm_desc,
[DECRYPTBYCERT(C.certificate_id, KE.crypt_property)] = DECRYPTBYCERT(C.certificate_id, KE.crypt_property),
SK.key_guid
FROM sys.symmetric_keys SK
INNER JOIN sys.key_encryptions KE ON KE.key_id = SK.symmetric_key_id
INNER JOIN sys.certificates C ON C.thumbprint = KE.thumbprint
WHERE KE.crypt_type = 'EPUC'
Now I wonder if I can recreate the symmetric key from this information inside another database. For CREATE CERTIFICATE
you can use FROM BINARY = 0x... WITH PRIVATE KEY ( BINARY = 0x...)
, but it seems the closest I get is
CREATE SYMMETRIC KEY TestKey
WITH
ALGORITHM = AES_256,
KEY_SOURCE = 'password to derive key',
IDENTITY_VALUE = 'password to derive guid'
ENCRYPTION BY CERTIFICATE TestCert;
Can anybody help me write a working statement to recreate the symmetric key?
I guess I will either need a way to generate a password that derives the same key (and ideally the same guid) again or find another option to specify the 'plaintext' symmetric key (EKM?). The original KEY_SOURCE
- and IDENTITY_VALUE
-properties are unknown to me.
Appendix: Demonstration, that key is valid
Prerequisites on SQL Server (I used SQL Server 2016):
CREATE CERTIFICATE TestCert
WITH SUBJECT = 'TestCert';
CREATE SYMMETRIC KEY TestKey
WITH
ALGORITHM = AES_256,
KEY_SOURCE = 'password to derive key',
IDENTITY_VALUE = 'password to derive guid'
ENCRYPTION BY CERTIFICATE TestCert;
Use query from above to retrieve AES-Key:
|| name || key_length || algorithm_desc || DECRYPTBYCERT(C.certificate_id, KE.crypt_property) || key_guid ||
| TestKey | 256 | AES_256 | 0xAF8C9D22CE9B6BBE5E4207608A2D4D9494B8532AD2F358C382F02BB3303A36E6 | 01DE2200-EF6C-3C1A-0F3A-889881EF77E7 |
Encrypt something
DECLARE @KeyGuid uniqueidentifier = '01DE2200-EF6C-3C1A-0F3A-889881EF77E7';
OPEN SYMMETRIC KEY TestKey
DECRYPTION BY CERTIFICATE [TestCert];
SELECT ENCRYPTBYKEY(@KeyGuid, N'blubb'); -- yields 0x0022DE016CEF1A3C0F3A889881EF77E70100000091B6D30FAB2FFBC7FFEAE32D3A52A6F8AEA2750CEBEBE6BCE33782AEC52A4E31B04FFBCCD06470242E585AA4261BC3B1
CLOSE SYMMETRIC KEY TestKey;
Then this LINQPad-query (C# Program) can be used to decrypt the encrypted values again (Strictly proof-of-concept quality!):
void Main()
{
AesManaged myAes = new AesManaged();
// Override the cipher mode and padding. Key and IV are passed in below
myAes.Mode = CipherMode.CBC;
myAes.Padding = PaddingMode.None;
var Key = StringToByteArray("0xAF8C9D22CE9B6BBE5E4207608A2D4D9494B8532AD2F358C382F02BB3303A36E6"); // Byte array representing the key
var encrypted = StringToByteArray("0x0022DE016CEF1A3C0F3A889881EF77E70100000091B6D30FAB2FFBC7FFEAE32D3A52A6F8AEA2750CEBEBE6BCE33782AEC52A4E31B04FFBCCD06470242E585AA4261BC3B1");
// Following fields are according to https://blogs.msdn.microsoft.com/sqlsecurity/2009/03/30/sql-server-encryptbykey-cryptographic-message-description/
var KeyGUID = new Guid(encrypted.Slice(0, 16)).Dump("Guid");
var EncryptionHeader = encrypted.Slice(16, 4);
//var Headerversion = EncryptionHeader.Slice(0, 1); // Could check for 0x01
//var ReservedBytes = EncryptionHeader.Slice(1, 3); // currently all 0x00
var EncryptedMessage = encrypted.Slice(20);
var InitializationVector = EncryptedMessage.Slice(0, myAes.BlockSize / 8);
var EncryptedData = EncryptedMessage.Slice(myAes.BlockSize / 8);
// We have everything to perform the decryption
var decryptor = myAes.CreateDecryptor(Key, InitializationVector);
var InnerMessage = decryptor.TransformFinalBlock(EncryptedData, 0, EncryptedData.Length);
// Encrypted result contaisn more fields
var InnerMessageHeader = InnerMessage.Slice(0, 8);
//var MagicNumber = InnerMessageHeader.Slice(0, 4); // Could check for 3131961357
var IntegrityBytesLength = BitConverter.ToUInt16(InnerMessageHeader.Slice(4, 2), 0).Dump("IntegrityBytesLength");
var PlaintextLength = BitConverter.ToUInt16(InnerMessageHeader.Slice(6, 2), 0).Dump("PlaintextLength");
//var IntegrityBytes = InnerMessage.Slice(8, IntegrityBytesLength).Dump("IntegrityBytes"); // Not used without "authenticator" in ENCRYPTBYKEY
// Our Plaintext (finally!) - Encoding needs to be changed if input to ENCRYPTBYKEY is not nvarchar
var Plaintext = new string(Encoding.Unicode.GetChars(InnerMessage.Slice(8 + IntegrityBytesLength, PlaintextLength))).Dump("Plaintext");
}
// Define other methods and classes here
public static byte StringToByteArray(string hex)
{
return Enumerable.Range(2, hex.Length - 2)
.Where(x => x % 2 == 0)
.Select(x => Convert.ToByte(hex.Substring(x, 2), 16))
.ToArray();
}
static class Extensions
{
public static byte Slice(this byte input, long startIndex, long? length = null)
{
var result = new byte[length ?? (input.LongLength - startIndex)];
Array.Copy(input, startIndex, result, 0, result.LongLength);
return result;
}
}
Output:
Guid
01de2200-ef6c-3c1a-0f3a-889881ef77e7
IntegrityBytesLength
0
PlaintextLength
10
Plaintext
blubb
sql-server encryption symmetric-key
bumped to the homepage by Community♦ 5 mins ago
This question has answers that may be good or bad; the system has marked it active so that they can be reviewed.
add a comment |
I found that for each encryption of a symmetric key an entry in sys.key_encryptions
is present and at least for ENCRYPTION BY CERTIFICATE
-type entries I can use the certificate of the specified thumbprint
to decrypt the crypt_property
:
SELECT
SK.name,
SK.key_length,
SK.algorithm_desc,
[DECRYPTBYCERT(C.certificate_id, KE.crypt_property)] = DECRYPTBYCERT(C.certificate_id, KE.crypt_property),
SK.key_guid
FROM sys.symmetric_keys SK
INNER JOIN sys.key_encryptions KE ON KE.key_id = SK.symmetric_key_id
INNER JOIN sys.certificates C ON C.thumbprint = KE.thumbprint
WHERE KE.crypt_type = 'EPUC'
Now I wonder if I can recreate the symmetric key from this information inside another database. For CREATE CERTIFICATE
you can use FROM BINARY = 0x... WITH PRIVATE KEY ( BINARY = 0x...)
, but it seems the closest I get is
CREATE SYMMETRIC KEY TestKey
WITH
ALGORITHM = AES_256,
KEY_SOURCE = 'password to derive key',
IDENTITY_VALUE = 'password to derive guid'
ENCRYPTION BY CERTIFICATE TestCert;
Can anybody help me write a working statement to recreate the symmetric key?
I guess I will either need a way to generate a password that derives the same key (and ideally the same guid) again or find another option to specify the 'plaintext' symmetric key (EKM?). The original KEY_SOURCE
- and IDENTITY_VALUE
-properties are unknown to me.
Appendix: Demonstration, that key is valid
Prerequisites on SQL Server (I used SQL Server 2016):
CREATE CERTIFICATE TestCert
WITH SUBJECT = 'TestCert';
CREATE SYMMETRIC KEY TestKey
WITH
ALGORITHM = AES_256,
KEY_SOURCE = 'password to derive key',
IDENTITY_VALUE = 'password to derive guid'
ENCRYPTION BY CERTIFICATE TestCert;
Use query from above to retrieve AES-Key:
|| name || key_length || algorithm_desc || DECRYPTBYCERT(C.certificate_id, KE.crypt_property) || key_guid ||
| TestKey | 256 | AES_256 | 0xAF8C9D22CE9B6BBE5E4207608A2D4D9494B8532AD2F358C382F02BB3303A36E6 | 01DE2200-EF6C-3C1A-0F3A-889881EF77E7 |
Encrypt something
DECLARE @KeyGuid uniqueidentifier = '01DE2200-EF6C-3C1A-0F3A-889881EF77E7';
OPEN SYMMETRIC KEY TestKey
DECRYPTION BY CERTIFICATE [TestCert];
SELECT ENCRYPTBYKEY(@KeyGuid, N'blubb'); -- yields 0x0022DE016CEF1A3C0F3A889881EF77E70100000091B6D30FAB2FFBC7FFEAE32D3A52A6F8AEA2750CEBEBE6BCE33782AEC52A4E31B04FFBCCD06470242E585AA4261BC3B1
CLOSE SYMMETRIC KEY TestKey;
Then this LINQPad-query (C# Program) can be used to decrypt the encrypted values again (Strictly proof-of-concept quality!):
void Main()
{
AesManaged myAes = new AesManaged();
// Override the cipher mode and padding. Key and IV are passed in below
myAes.Mode = CipherMode.CBC;
myAes.Padding = PaddingMode.None;
var Key = StringToByteArray("0xAF8C9D22CE9B6BBE5E4207608A2D4D9494B8532AD2F358C382F02BB3303A36E6"); // Byte array representing the key
var encrypted = StringToByteArray("0x0022DE016CEF1A3C0F3A889881EF77E70100000091B6D30FAB2FFBC7FFEAE32D3A52A6F8AEA2750CEBEBE6BCE33782AEC52A4E31B04FFBCCD06470242E585AA4261BC3B1");
// Following fields are according to https://blogs.msdn.microsoft.com/sqlsecurity/2009/03/30/sql-server-encryptbykey-cryptographic-message-description/
var KeyGUID = new Guid(encrypted.Slice(0, 16)).Dump("Guid");
var EncryptionHeader = encrypted.Slice(16, 4);
//var Headerversion = EncryptionHeader.Slice(0, 1); // Could check for 0x01
//var ReservedBytes = EncryptionHeader.Slice(1, 3); // currently all 0x00
var EncryptedMessage = encrypted.Slice(20);
var InitializationVector = EncryptedMessage.Slice(0, myAes.BlockSize / 8);
var EncryptedData = EncryptedMessage.Slice(myAes.BlockSize / 8);
// We have everything to perform the decryption
var decryptor = myAes.CreateDecryptor(Key, InitializationVector);
var InnerMessage = decryptor.TransformFinalBlock(EncryptedData, 0, EncryptedData.Length);
// Encrypted result contaisn more fields
var InnerMessageHeader = InnerMessage.Slice(0, 8);
//var MagicNumber = InnerMessageHeader.Slice(0, 4); // Could check for 3131961357
var IntegrityBytesLength = BitConverter.ToUInt16(InnerMessageHeader.Slice(4, 2), 0).Dump("IntegrityBytesLength");
var PlaintextLength = BitConverter.ToUInt16(InnerMessageHeader.Slice(6, 2), 0).Dump("PlaintextLength");
//var IntegrityBytes = InnerMessage.Slice(8, IntegrityBytesLength).Dump("IntegrityBytes"); // Not used without "authenticator" in ENCRYPTBYKEY
// Our Plaintext (finally!) - Encoding needs to be changed if input to ENCRYPTBYKEY is not nvarchar
var Plaintext = new string(Encoding.Unicode.GetChars(InnerMessage.Slice(8 + IntegrityBytesLength, PlaintextLength))).Dump("Plaintext");
}
// Define other methods and classes here
public static byte StringToByteArray(string hex)
{
return Enumerable.Range(2, hex.Length - 2)
.Where(x => x % 2 == 0)
.Select(x => Convert.ToByte(hex.Substring(x, 2), 16))
.ToArray();
}
static class Extensions
{
public static byte Slice(this byte input, long startIndex, long? length = null)
{
var result = new byte[length ?? (input.LongLength - startIndex)];
Array.Copy(input, startIndex, result, 0, result.LongLength);
return result;
}
}
Output:
Guid
01de2200-ef6c-3c1a-0f3a-889881ef77e7
IntegrityBytesLength
0
PlaintextLength
10
Plaintext
blubb
sql-server encryption symmetric-key
bumped to the homepage by Community♦ 5 mins ago
This question has answers that may be good or bad; the system has marked it active so that they can be reviewed.
Great would be to avoid the problem of feedback.azure.com/forums/908035-sql-server/suggestions/… as well
– TheConstructor
Jun 18 '18 at 10:14
1
Given that you can extract the symmetric key details, you should be able to take that and implement a function (probably outside of SQL Server) that implements the 256 bit AES algorithm with that specific key. You could then compile it back into SQL Server as a CLR function to perform the decryption, and at least rotate the data to being encrypted by a new, known symmetric key. Sebastian Meine may be able to help you with more specifics on how to implement that.
– mathewb
Jun 18 '18 at 17:46
@mathewb CLR function is not what I currently aim for. Ideally I can just create a database and create the key there, so that I can extract the relevant parts from the other database, without the need to start out on a full-backup.
– TheConstructor
Jun 19 '18 at 11:44
add a comment |
I found that for each encryption of a symmetric key an entry in sys.key_encryptions
is present and at least for ENCRYPTION BY CERTIFICATE
-type entries I can use the certificate of the specified thumbprint
to decrypt the crypt_property
:
SELECT
SK.name,
SK.key_length,
SK.algorithm_desc,
[DECRYPTBYCERT(C.certificate_id, KE.crypt_property)] = DECRYPTBYCERT(C.certificate_id, KE.crypt_property),
SK.key_guid
FROM sys.symmetric_keys SK
INNER JOIN sys.key_encryptions KE ON KE.key_id = SK.symmetric_key_id
INNER JOIN sys.certificates C ON C.thumbprint = KE.thumbprint
WHERE KE.crypt_type = 'EPUC'
Now I wonder if I can recreate the symmetric key from this information inside another database. For CREATE CERTIFICATE
you can use FROM BINARY = 0x... WITH PRIVATE KEY ( BINARY = 0x...)
, but it seems the closest I get is
CREATE SYMMETRIC KEY TestKey
WITH
ALGORITHM = AES_256,
KEY_SOURCE = 'password to derive key',
IDENTITY_VALUE = 'password to derive guid'
ENCRYPTION BY CERTIFICATE TestCert;
Can anybody help me write a working statement to recreate the symmetric key?
I guess I will either need a way to generate a password that derives the same key (and ideally the same guid) again or find another option to specify the 'plaintext' symmetric key (EKM?). The original KEY_SOURCE
- and IDENTITY_VALUE
-properties are unknown to me.
Appendix: Demonstration, that key is valid
Prerequisites on SQL Server (I used SQL Server 2016):
CREATE CERTIFICATE TestCert
WITH SUBJECT = 'TestCert';
CREATE SYMMETRIC KEY TestKey
WITH
ALGORITHM = AES_256,
KEY_SOURCE = 'password to derive key',
IDENTITY_VALUE = 'password to derive guid'
ENCRYPTION BY CERTIFICATE TestCert;
Use query from above to retrieve AES-Key:
|| name || key_length || algorithm_desc || DECRYPTBYCERT(C.certificate_id, KE.crypt_property) || key_guid ||
| TestKey | 256 | AES_256 | 0xAF8C9D22CE9B6BBE5E4207608A2D4D9494B8532AD2F358C382F02BB3303A36E6 | 01DE2200-EF6C-3C1A-0F3A-889881EF77E7 |
Encrypt something
DECLARE @KeyGuid uniqueidentifier = '01DE2200-EF6C-3C1A-0F3A-889881EF77E7';
OPEN SYMMETRIC KEY TestKey
DECRYPTION BY CERTIFICATE [TestCert];
SELECT ENCRYPTBYKEY(@KeyGuid, N'blubb'); -- yields 0x0022DE016CEF1A3C0F3A889881EF77E70100000091B6D30FAB2FFBC7FFEAE32D3A52A6F8AEA2750CEBEBE6BCE33782AEC52A4E31B04FFBCCD06470242E585AA4261BC3B1
CLOSE SYMMETRIC KEY TestKey;
Then this LINQPad-query (C# Program) can be used to decrypt the encrypted values again (Strictly proof-of-concept quality!):
void Main()
{
AesManaged myAes = new AesManaged();
// Override the cipher mode and padding. Key and IV are passed in below
myAes.Mode = CipherMode.CBC;
myAes.Padding = PaddingMode.None;
var Key = StringToByteArray("0xAF8C9D22CE9B6BBE5E4207608A2D4D9494B8532AD2F358C382F02BB3303A36E6"); // Byte array representing the key
var encrypted = StringToByteArray("0x0022DE016CEF1A3C0F3A889881EF77E70100000091B6D30FAB2FFBC7FFEAE32D3A52A6F8AEA2750CEBEBE6BCE33782AEC52A4E31B04FFBCCD06470242E585AA4261BC3B1");
// Following fields are according to https://blogs.msdn.microsoft.com/sqlsecurity/2009/03/30/sql-server-encryptbykey-cryptographic-message-description/
var KeyGUID = new Guid(encrypted.Slice(0, 16)).Dump("Guid");
var EncryptionHeader = encrypted.Slice(16, 4);
//var Headerversion = EncryptionHeader.Slice(0, 1); // Could check for 0x01
//var ReservedBytes = EncryptionHeader.Slice(1, 3); // currently all 0x00
var EncryptedMessage = encrypted.Slice(20);
var InitializationVector = EncryptedMessage.Slice(0, myAes.BlockSize / 8);
var EncryptedData = EncryptedMessage.Slice(myAes.BlockSize / 8);
// We have everything to perform the decryption
var decryptor = myAes.CreateDecryptor(Key, InitializationVector);
var InnerMessage = decryptor.TransformFinalBlock(EncryptedData, 0, EncryptedData.Length);
// Encrypted result contaisn more fields
var InnerMessageHeader = InnerMessage.Slice(0, 8);
//var MagicNumber = InnerMessageHeader.Slice(0, 4); // Could check for 3131961357
var IntegrityBytesLength = BitConverter.ToUInt16(InnerMessageHeader.Slice(4, 2), 0).Dump("IntegrityBytesLength");
var PlaintextLength = BitConverter.ToUInt16(InnerMessageHeader.Slice(6, 2), 0).Dump("PlaintextLength");
//var IntegrityBytes = InnerMessage.Slice(8, IntegrityBytesLength).Dump("IntegrityBytes"); // Not used without "authenticator" in ENCRYPTBYKEY
// Our Plaintext (finally!) - Encoding needs to be changed if input to ENCRYPTBYKEY is not nvarchar
var Plaintext = new string(Encoding.Unicode.GetChars(InnerMessage.Slice(8 + IntegrityBytesLength, PlaintextLength))).Dump("Plaintext");
}
// Define other methods and classes here
public static byte StringToByteArray(string hex)
{
return Enumerable.Range(2, hex.Length - 2)
.Where(x => x % 2 == 0)
.Select(x => Convert.ToByte(hex.Substring(x, 2), 16))
.ToArray();
}
static class Extensions
{
public static byte Slice(this byte input, long startIndex, long? length = null)
{
var result = new byte[length ?? (input.LongLength - startIndex)];
Array.Copy(input, startIndex, result, 0, result.LongLength);
return result;
}
}
Output:
Guid
01de2200-ef6c-3c1a-0f3a-889881ef77e7
IntegrityBytesLength
0
PlaintextLength
10
Plaintext
blubb
sql-server encryption symmetric-key
I found that for each encryption of a symmetric key an entry in sys.key_encryptions
is present and at least for ENCRYPTION BY CERTIFICATE
-type entries I can use the certificate of the specified thumbprint
to decrypt the crypt_property
:
SELECT
SK.name,
SK.key_length,
SK.algorithm_desc,
[DECRYPTBYCERT(C.certificate_id, KE.crypt_property)] = DECRYPTBYCERT(C.certificate_id, KE.crypt_property),
SK.key_guid
FROM sys.symmetric_keys SK
INNER JOIN sys.key_encryptions KE ON KE.key_id = SK.symmetric_key_id
INNER JOIN sys.certificates C ON C.thumbprint = KE.thumbprint
WHERE KE.crypt_type = 'EPUC'
Now I wonder if I can recreate the symmetric key from this information inside another database. For CREATE CERTIFICATE
you can use FROM BINARY = 0x... WITH PRIVATE KEY ( BINARY = 0x...)
, but it seems the closest I get is
CREATE SYMMETRIC KEY TestKey
WITH
ALGORITHM = AES_256,
KEY_SOURCE = 'password to derive key',
IDENTITY_VALUE = 'password to derive guid'
ENCRYPTION BY CERTIFICATE TestCert;
Can anybody help me write a working statement to recreate the symmetric key?
I guess I will either need a way to generate a password that derives the same key (and ideally the same guid) again or find another option to specify the 'plaintext' symmetric key (EKM?). The original KEY_SOURCE
- and IDENTITY_VALUE
-properties are unknown to me.
Appendix: Demonstration, that key is valid
Prerequisites on SQL Server (I used SQL Server 2016):
CREATE CERTIFICATE TestCert
WITH SUBJECT = 'TestCert';
CREATE SYMMETRIC KEY TestKey
WITH
ALGORITHM = AES_256,
KEY_SOURCE = 'password to derive key',
IDENTITY_VALUE = 'password to derive guid'
ENCRYPTION BY CERTIFICATE TestCert;
Use query from above to retrieve AES-Key:
|| name || key_length || algorithm_desc || DECRYPTBYCERT(C.certificate_id, KE.crypt_property) || key_guid ||
| TestKey | 256 | AES_256 | 0xAF8C9D22CE9B6BBE5E4207608A2D4D9494B8532AD2F358C382F02BB3303A36E6 | 01DE2200-EF6C-3C1A-0F3A-889881EF77E7 |
Encrypt something
DECLARE @KeyGuid uniqueidentifier = '01DE2200-EF6C-3C1A-0F3A-889881EF77E7';
OPEN SYMMETRIC KEY TestKey
DECRYPTION BY CERTIFICATE [TestCert];
SELECT ENCRYPTBYKEY(@KeyGuid, N'blubb'); -- yields 0x0022DE016CEF1A3C0F3A889881EF77E70100000091B6D30FAB2FFBC7FFEAE32D3A52A6F8AEA2750CEBEBE6BCE33782AEC52A4E31B04FFBCCD06470242E585AA4261BC3B1
CLOSE SYMMETRIC KEY TestKey;
Then this LINQPad-query (C# Program) can be used to decrypt the encrypted values again (Strictly proof-of-concept quality!):
void Main()
{
AesManaged myAes = new AesManaged();
// Override the cipher mode and padding. Key and IV are passed in below
myAes.Mode = CipherMode.CBC;
myAes.Padding = PaddingMode.None;
var Key = StringToByteArray("0xAF8C9D22CE9B6BBE5E4207608A2D4D9494B8532AD2F358C382F02BB3303A36E6"); // Byte array representing the key
var encrypted = StringToByteArray("0x0022DE016CEF1A3C0F3A889881EF77E70100000091B6D30FAB2FFBC7FFEAE32D3A52A6F8AEA2750CEBEBE6BCE33782AEC52A4E31B04FFBCCD06470242E585AA4261BC3B1");
// Following fields are according to https://blogs.msdn.microsoft.com/sqlsecurity/2009/03/30/sql-server-encryptbykey-cryptographic-message-description/
var KeyGUID = new Guid(encrypted.Slice(0, 16)).Dump("Guid");
var EncryptionHeader = encrypted.Slice(16, 4);
//var Headerversion = EncryptionHeader.Slice(0, 1); // Could check for 0x01
//var ReservedBytes = EncryptionHeader.Slice(1, 3); // currently all 0x00
var EncryptedMessage = encrypted.Slice(20);
var InitializationVector = EncryptedMessage.Slice(0, myAes.BlockSize / 8);
var EncryptedData = EncryptedMessage.Slice(myAes.BlockSize / 8);
// We have everything to perform the decryption
var decryptor = myAes.CreateDecryptor(Key, InitializationVector);
var InnerMessage = decryptor.TransformFinalBlock(EncryptedData, 0, EncryptedData.Length);
// Encrypted result contaisn more fields
var InnerMessageHeader = InnerMessage.Slice(0, 8);
//var MagicNumber = InnerMessageHeader.Slice(0, 4); // Could check for 3131961357
var IntegrityBytesLength = BitConverter.ToUInt16(InnerMessageHeader.Slice(4, 2), 0).Dump("IntegrityBytesLength");
var PlaintextLength = BitConverter.ToUInt16(InnerMessageHeader.Slice(6, 2), 0).Dump("PlaintextLength");
//var IntegrityBytes = InnerMessage.Slice(8, IntegrityBytesLength).Dump("IntegrityBytes"); // Not used without "authenticator" in ENCRYPTBYKEY
// Our Plaintext (finally!) - Encoding needs to be changed if input to ENCRYPTBYKEY is not nvarchar
var Plaintext = new string(Encoding.Unicode.GetChars(InnerMessage.Slice(8 + IntegrityBytesLength, PlaintextLength))).Dump("Plaintext");
}
// Define other methods and classes here
public static byte StringToByteArray(string hex)
{
return Enumerable.Range(2, hex.Length - 2)
.Where(x => x % 2 == 0)
.Select(x => Convert.ToByte(hex.Substring(x, 2), 16))
.ToArray();
}
static class Extensions
{
public static byte Slice(this byte input, long startIndex, long? length = null)
{
var result = new byte[length ?? (input.LongLength - startIndex)];
Array.Copy(input, startIndex, result, 0, result.LongLength);
return result;
}
}
Output:
Guid
01de2200-ef6c-3c1a-0f3a-889881ef77e7
IntegrityBytesLength
0
PlaintextLength
10
Plaintext
blubb
sql-server encryption symmetric-key
sql-server encryption symmetric-key
edited Jun 19 '18 at 11:37
TheConstructor
asked Jun 18 '18 at 9:37
TheConstructorTheConstructor
1065
1065
bumped to the homepage by Community♦ 5 mins ago
This question has answers that may be good or bad; the system has marked it active so that they can be reviewed.
bumped to the homepage by Community♦ 5 mins ago
This question has answers that may be good or bad; the system has marked it active so that they can be reviewed.
Great would be to avoid the problem of feedback.azure.com/forums/908035-sql-server/suggestions/… as well
– TheConstructor
Jun 18 '18 at 10:14
1
Given that you can extract the symmetric key details, you should be able to take that and implement a function (probably outside of SQL Server) that implements the 256 bit AES algorithm with that specific key. You could then compile it back into SQL Server as a CLR function to perform the decryption, and at least rotate the data to being encrypted by a new, known symmetric key. Sebastian Meine may be able to help you with more specifics on how to implement that.
– mathewb
Jun 18 '18 at 17:46
@mathewb CLR function is not what I currently aim for. Ideally I can just create a database and create the key there, so that I can extract the relevant parts from the other database, without the need to start out on a full-backup.
– TheConstructor
Jun 19 '18 at 11:44
add a comment |
Great would be to avoid the problem of feedback.azure.com/forums/908035-sql-server/suggestions/… as well
– TheConstructor
Jun 18 '18 at 10:14
1
Given that you can extract the symmetric key details, you should be able to take that and implement a function (probably outside of SQL Server) that implements the 256 bit AES algorithm with that specific key. You could then compile it back into SQL Server as a CLR function to perform the decryption, and at least rotate the data to being encrypted by a new, known symmetric key. Sebastian Meine may be able to help you with more specifics on how to implement that.
– mathewb
Jun 18 '18 at 17:46
@mathewb CLR function is not what I currently aim for. Ideally I can just create a database and create the key there, so that I can extract the relevant parts from the other database, without the need to start out on a full-backup.
– TheConstructor
Jun 19 '18 at 11:44
Great would be to avoid the problem of feedback.azure.com/forums/908035-sql-server/suggestions/… as well
– TheConstructor
Jun 18 '18 at 10:14
Great would be to avoid the problem of feedback.azure.com/forums/908035-sql-server/suggestions/… as well
– TheConstructor
Jun 18 '18 at 10:14
1
1
Given that you can extract the symmetric key details, you should be able to take that and implement a function (probably outside of SQL Server) that implements the 256 bit AES algorithm with that specific key. You could then compile it back into SQL Server as a CLR function to perform the decryption, and at least rotate the data to being encrypted by a new, known symmetric key. Sebastian Meine may be able to help you with more specifics on how to implement that.
– mathewb
Jun 18 '18 at 17:46
Given that you can extract the symmetric key details, you should be able to take that and implement a function (probably outside of SQL Server) that implements the 256 bit AES algorithm with that specific key. You could then compile it back into SQL Server as a CLR function to perform the decryption, and at least rotate the data to being encrypted by a new, known symmetric key. Sebastian Meine may be able to help you with more specifics on how to implement that.
– mathewb
Jun 18 '18 at 17:46
@mathewb CLR function is not what I currently aim for. Ideally I can just create a database and create the key there, so that I can extract the relevant parts from the other database, without the need to start out on a full-backup.
– TheConstructor
Jun 19 '18 at 11:44
@mathewb CLR function is not what I currently aim for. Ideally I can just create a database and create the key there, so that I can extract the relevant parts from the other database, without the need to start out on a full-backup.
– TheConstructor
Jun 19 '18 at 11:44
add a comment |
1 Answer
1
active
oldest
votes
If anyone can simply write a sql statement to extract the passwords or arguments or recreate the same key, it would defeat the encryption. An AES_256 key has 2^256 possibilities. The encryption in SQL Server is based on a hierarchy of keys protecting each other. And because the symmetric keys are protected by a certificate or asymmetric key and you can't get to the private key, which itself is protected by other keys, you won't be able to break the system unless you can break the data protection API on the host. If you are trying to solve a problem where you've lost control of the encrypted data and need to recover, then it is possible to do if you know only the Key_source argument used to create the key originally because the first 16 bytes of data encrypted with a symmetric key is the guid and that can be replaced with the guid of the new key prior to decryption.
I can decrypt the data, but I want to recreate the same key in another database. Also the query stated in the question uses the certificate (where I need to have access to the private key) to give me the real AES_256 key I "just" look for a way to reuse it.
– TheConstructor
Jun 19 '18 at 9:18
As shown by the C# implementation I do get indeed the (private) symmetric key. As such the first part of this answer is invalid.
– TheConstructor
Jun 19 '18 at 12:47
Symmetric keys don't have public and private keys. There is only one key and its encrypted in the system tables. There are several methods you can use to place the same symmetric key on a different database or server. One is to know, in advance, and use the key_source and identity_value parameters and use those on the destination. the other method would be to backup the original database and database master key separately and restore them both on the destination server.
– Michael Keleher
Jun 19 '18 at 12:56
add a comment |
Your Answer
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "182"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fdba.stackexchange.com%2fquestions%2f209905%2frecreate-symmetric-key-of-unknown-create-symmetric-key%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
If anyone can simply write a sql statement to extract the passwords or arguments or recreate the same key, it would defeat the encryption. An AES_256 key has 2^256 possibilities. The encryption in SQL Server is based on a hierarchy of keys protecting each other. And because the symmetric keys are protected by a certificate or asymmetric key and you can't get to the private key, which itself is protected by other keys, you won't be able to break the system unless you can break the data protection API on the host. If you are trying to solve a problem where you've lost control of the encrypted data and need to recover, then it is possible to do if you know only the Key_source argument used to create the key originally because the first 16 bytes of data encrypted with a symmetric key is the guid and that can be replaced with the guid of the new key prior to decryption.
I can decrypt the data, but I want to recreate the same key in another database. Also the query stated in the question uses the certificate (where I need to have access to the private key) to give me the real AES_256 key I "just" look for a way to reuse it.
– TheConstructor
Jun 19 '18 at 9:18
As shown by the C# implementation I do get indeed the (private) symmetric key. As such the first part of this answer is invalid.
– TheConstructor
Jun 19 '18 at 12:47
Symmetric keys don't have public and private keys. There is only one key and its encrypted in the system tables. There are several methods you can use to place the same symmetric key on a different database or server. One is to know, in advance, and use the key_source and identity_value parameters and use those on the destination. the other method would be to backup the original database and database master key separately and restore them both on the destination server.
– Michael Keleher
Jun 19 '18 at 12:56
add a comment |
If anyone can simply write a sql statement to extract the passwords or arguments or recreate the same key, it would defeat the encryption. An AES_256 key has 2^256 possibilities. The encryption in SQL Server is based on a hierarchy of keys protecting each other. And because the symmetric keys are protected by a certificate or asymmetric key and you can't get to the private key, which itself is protected by other keys, you won't be able to break the system unless you can break the data protection API on the host. If you are trying to solve a problem where you've lost control of the encrypted data and need to recover, then it is possible to do if you know only the Key_source argument used to create the key originally because the first 16 bytes of data encrypted with a symmetric key is the guid and that can be replaced with the guid of the new key prior to decryption.
I can decrypt the data, but I want to recreate the same key in another database. Also the query stated in the question uses the certificate (where I need to have access to the private key) to give me the real AES_256 key I "just" look for a way to reuse it.
– TheConstructor
Jun 19 '18 at 9:18
As shown by the C# implementation I do get indeed the (private) symmetric key. As such the first part of this answer is invalid.
– TheConstructor
Jun 19 '18 at 12:47
Symmetric keys don't have public and private keys. There is only one key and its encrypted in the system tables. There are several methods you can use to place the same symmetric key on a different database or server. One is to know, in advance, and use the key_source and identity_value parameters and use those on the destination. the other method would be to backup the original database and database master key separately and restore them both on the destination server.
– Michael Keleher
Jun 19 '18 at 12:56
add a comment |
If anyone can simply write a sql statement to extract the passwords or arguments or recreate the same key, it would defeat the encryption. An AES_256 key has 2^256 possibilities. The encryption in SQL Server is based on a hierarchy of keys protecting each other. And because the symmetric keys are protected by a certificate or asymmetric key and you can't get to the private key, which itself is protected by other keys, you won't be able to break the system unless you can break the data protection API on the host. If you are trying to solve a problem where you've lost control of the encrypted data and need to recover, then it is possible to do if you know only the Key_source argument used to create the key originally because the first 16 bytes of data encrypted with a symmetric key is the guid and that can be replaced with the guid of the new key prior to decryption.
If anyone can simply write a sql statement to extract the passwords or arguments or recreate the same key, it would defeat the encryption. An AES_256 key has 2^256 possibilities. The encryption in SQL Server is based on a hierarchy of keys protecting each other. And because the symmetric keys are protected by a certificate or asymmetric key and you can't get to the private key, which itself is protected by other keys, you won't be able to break the system unless you can break the data protection API on the host. If you are trying to solve a problem where you've lost control of the encrypted data and need to recover, then it is possible to do if you know only the Key_source argument used to create the key originally because the first 16 bytes of data encrypted with a symmetric key is the guid and that can be replaced with the guid of the new key prior to decryption.
answered Jun 18 '18 at 16:45
Michael KeleherMichael Keleher
659310
659310
I can decrypt the data, but I want to recreate the same key in another database. Also the query stated in the question uses the certificate (where I need to have access to the private key) to give me the real AES_256 key I "just" look for a way to reuse it.
– TheConstructor
Jun 19 '18 at 9:18
As shown by the C# implementation I do get indeed the (private) symmetric key. As such the first part of this answer is invalid.
– TheConstructor
Jun 19 '18 at 12:47
Symmetric keys don't have public and private keys. There is only one key and its encrypted in the system tables. There are several methods you can use to place the same symmetric key on a different database or server. One is to know, in advance, and use the key_source and identity_value parameters and use those on the destination. the other method would be to backup the original database and database master key separately and restore them both on the destination server.
– Michael Keleher
Jun 19 '18 at 12:56
add a comment |
I can decrypt the data, but I want to recreate the same key in another database. Also the query stated in the question uses the certificate (where I need to have access to the private key) to give me the real AES_256 key I "just" look for a way to reuse it.
– TheConstructor
Jun 19 '18 at 9:18
As shown by the C# implementation I do get indeed the (private) symmetric key. As such the first part of this answer is invalid.
– TheConstructor
Jun 19 '18 at 12:47
Symmetric keys don't have public and private keys. There is only one key and its encrypted in the system tables. There are several methods you can use to place the same symmetric key on a different database or server. One is to know, in advance, and use the key_source and identity_value parameters and use those on the destination. the other method would be to backup the original database and database master key separately and restore them both on the destination server.
– Michael Keleher
Jun 19 '18 at 12:56
I can decrypt the data, but I want to recreate the same key in another database. Also the query stated in the question uses the certificate (where I need to have access to the private key) to give me the real AES_256 key I "just" look for a way to reuse it.
– TheConstructor
Jun 19 '18 at 9:18
I can decrypt the data, but I want to recreate the same key in another database. Also the query stated in the question uses the certificate (where I need to have access to the private key) to give me the real AES_256 key I "just" look for a way to reuse it.
– TheConstructor
Jun 19 '18 at 9:18
As shown by the C# implementation I do get indeed the (private) symmetric key. As such the first part of this answer is invalid.
– TheConstructor
Jun 19 '18 at 12:47
As shown by the C# implementation I do get indeed the (private) symmetric key. As such the first part of this answer is invalid.
– TheConstructor
Jun 19 '18 at 12:47
Symmetric keys don't have public and private keys. There is only one key and its encrypted in the system tables. There are several methods you can use to place the same symmetric key on a different database or server. One is to know, in advance, and use the key_source and identity_value parameters and use those on the destination. the other method would be to backup the original database and database master key separately and restore them both on the destination server.
– Michael Keleher
Jun 19 '18 at 12:56
Symmetric keys don't have public and private keys. There is only one key and its encrypted in the system tables. There are several methods you can use to place the same symmetric key on a different database or server. One is to know, in advance, and use the key_source and identity_value parameters and use those on the destination. the other method would be to backup the original database and database master key separately and restore them both on the destination server.
– Michael Keleher
Jun 19 '18 at 12:56
add a comment |
Thanks for contributing an answer to Database Administrators Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fdba.stackexchange.com%2fquestions%2f209905%2frecreate-symmetric-key-of-unknown-create-symmetric-key%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Great would be to avoid the problem of feedback.azure.com/forums/908035-sql-server/suggestions/… as well
– TheConstructor
Jun 18 '18 at 10:14
1
Given that you can extract the symmetric key details, you should be able to take that and implement a function (probably outside of SQL Server) that implements the 256 bit AES algorithm with that specific key. You could then compile it back into SQL Server as a CLR function to perform the decryption, and at least rotate the data to being encrypted by a new, known symmetric key. Sebastian Meine may be able to help you with more specifics on how to implement that.
– mathewb
Jun 18 '18 at 17:46
@mathewb CLR function is not what I currently aim for. Ideally I can just create a database and create the key there, so that I can extract the relevant parts from the other database, without the need to start out on a full-backup.
– TheConstructor
Jun 19 '18 at 11:44