我想加密 SQL-Server 上的数据并在 .NET 应用程序上解密。在我的情况下,最好的方法是使用证书。
在我的测试数据库中,我必须创建一个主密钥:
CREATE MASTER KEY ENCRPTION
BY PASSWORD = 'TestEncryption1212'
然后我在 SQL-Server 上创建了一个证书
CREATE CERTIFICATE TestCertificate1212
WITH SUBJECT = 'TestEncryption1212'
接下来我将它导出到文件系统:
BACKUP CERTIFICATE TestCertificate1212
TO FILE = 'C:\temp\TestCertificate1212.cer'
WITH PRIVATE KEY (
FILE = 'C:\temp\TestPrivateKey1212.pvk',
ENCRYPTION BY PASSWORD = 'TestEncryption1212'
)
如果我添加一个
DECRYPT BY PASSWORD = 'TestEncryption1212'
我收到一条错误消息,指出私钥已由主密码加密。
我在我的测试数据库中加密了一个列
ALTER TABLE dbo.Encrypt
ADD EncryptedCol varbinary (256)
UPDATE dbo.Encrypt
SET EncryptedCol =
ENCRYPTBYCERT(
CERT_ID('TestCertificate1212'),
ClearTextCol
)
到目前为止,一切都很好。
下一步是生成一个 PFX 文件,它将证书与私钥文件结合起来
我将 cmd 中的目录更改为 pvk2pfx.exe 所在的文件夹并执行它:
>cd "Program Files\Microsoft SDK
s\Windows\v6.1\Bin"
>pvk2pfx.exe -pvk C:\temp\TestPrivateKey1212.pvk -spc C:\temp\TestCertificate1212.cer -pfx C:\temp\TestPFX.pfx
在我的 .NET 应用程序(C#-ConsoleApplication)中,我通过 SqlConnection 获取数据。我将数据传递给我调用的函数
public string DecryptDocIDWithFileCert(string pfxFilePath, byte[] EncryptedDocID)
此函数应打开证书并解密数据并将明文返回给应用程序:
public string DecryptDocIDWithFileCert(string pfxFilePath, byte[] EncryptedDocID)
{
string DecryptedDocID = "";
X509Certificate2 cert = new X509Certificate2(pfxFilePath, "TestEncryption1212");
if (cert == null)
{
throw new Exception("Certificate " + pfxFilePath + " Does not exist");
}
if (cert.HasPrivateKey)
{
RSACryptoServiceProvider RsaCSP = (RSACryptoServiceProvider)cert.PrivateKey;
byte[] ret = RsaCSP.Decrypt(EncryptedDocID, true);
if (ret == null)
{
throw new Exception("Decryption with RSA failed");
}
DecryptedDocID = System.Text.Encoding.UTF8.GetString(ret);
}
else
{
throw new Exception("Certificate " + pfxFilePath + " has no Private Key; ");
}
return DecryptedDocID;
}
当涉及到解密时,我得到了错误:
System.Security.Cryptography.CryptographicException: The specified network password is not correct.
at System.Security.Cryptography.CryptographicException.ThrowCryptogaphicException(Int32 hr)
at System.Security.Cryptography.X509Certificates.X509Utils._LoadCertFromFile(String fileName, IntPtr password, UInt32 dwFlags, Boolean persistKeySet, SafeCertContextHandle& pCertCtx)
at System.Security.Cryptography.X509Certificates.X509Certificate.LoadCertificateFromFile(String fileName, Object password, X509KeyStorageFlags keyStorageFlags)
at System.Security.Cryptography.X509Certificates.X509Certificate2..ctor(String fileName, String password)
at TestDecryption.MyDecryptor.DecryptDocIDWithFileCert(String pfxFilePath, Byte[] EncryptedDocID) in C:\Users\developmentUser\Documents\Visual Studio 2008\Projects\TestDecryption\TestDecryption\MyDecryptor.cs:line 57
at TestDecryption.Program.Main(String[] args) in C:\Users\developmentUser\Documents\Visual Studio 2008\Projects\TestDecryption\TestDecryption\Program.cs:line 37
我厌倦了寻找错误。有没有人看到错误并可以告诉我我做错了什么。我认为问题在于私钥是用主密钥加密的,我无法解密它。我想我需要的只是一个 sql 语句,我可以在没有主密钥的情况下设置私钥的密码?还是我走错了路?
请帮我!
更新
如果我使用以下命令在 SQL_Server 之外制作证书:
C:\temp\createCert>makecert -sv PrivateKey.pvk -n "cn=TestCertificate" TestCerti
ficate.cer -b 01/01/2013 -e 01/01/2014 -sky Exchange -pe
再次运行我所有的 SQL 脚本:
ALTER TABLE dbo.Encrypt
DROP COLUMN EncryptedCol
DROP CERTIFICATE TestCertificate1212
DROP MASTER KEY
CREATE CERTIFICATE TestCertificate
FROM FILE = 'C:\TEMP\createCert\TestCertificate.cer'
WITH PRIVATE KEY (
FILE = 'C:\TEMP\createCert\PrivateKey.pvk',
ENCRYPTION BY PASSWORD = 'TestEncryption123'
-- DECRYPTION BY PASSWORD = 'TestEncryption123'
)
ALTER TABLE dbo.Encrypt
ADD EncryptedCol varbinary (256)
UPDATE dbo.Encrypt
SET EncryptedCol = ENCRYPTBYCERT(CERT_ID('TestCertificate'),SecondCol)
然后尝试解密它我得到几个错误:
我用的八点
byte [] ret = RsaCSP.Decrypt(EncryptedDochID, true);
并得到:
System.Security.Cryptography.CryptographicException: Error occurred while decoding OAEP padding.
at System.Security.Cryptography.Utils._DecryptPKWin2KEnh(SafeKeyHandle hPubKey, Byte[] key, Boolean fOAEP, Int32& hr)
at System.Security.Cryptography.RSACryptoServiceProvider.Decrypt(Byte[] rgb,Boolean fOAEP)
at TestDecryption.MyDecryptor.DecryptDocIDWithFileCert(String pfxFilePath, Byte[] EncryptedDocID) in C:\Users\developmentUser\Documents\Visual Studio 2008\Projects\TestDecryption\TestDecryption\MyDecryptor.cs:line 71
at TestDecryption.Program.Main(String[] args) in C:\Users\developmentUser\Documents\Visual Studio 2008\Projects\TestDecryption\TestDecryption\Program.cs:line 37
或者我使用:
byte [] ret = RsaCSP.Decrypt(EncryptedDochID, false);
并得到:
System.Security.Cryptography.CryptographicException: Bad Data.
at System.Security.Cryptography.CryptographicException.ThrowCryptogaphicException(Int32 hr)
at System.Security.Cryptography.Utils._DecryptKey(SafeKeyHandle hPubKey, Byte[] key, Int32 dwFlags)
at System.Security.Cryptography.RSACryptoServiceProvider.Decrypt(Byte[] rgb, Boolean fOAEP)
at TestDecryption.MyDecryptor.DecryptDocIDWithFileCert(String pfxFilePath, Byte[] EncryptedDocID) in C:\Users\developmentUser\Documents\Visual Studio 2008\Projects\TestDecryption\TestDecryption\MyDecryptor.cs:line 71
at TestDecryption.Program.Main(String[] args) in C:\Users\developmentUser\Documents\Visual Studio 2008\Projects\TestDecryption\TestDecryption\Program.cs:line 37
或者
System.Security.Cryptography.CryptographicException: Not enough storage is available to process this command.
at System.Security.Cryptography.CryptographicException.ThrowCryptogaphicException(Int32 hr)
at System.Security.Cryptography.Utils._DecryptKey(SafeKeyHandle hPubKey, Byte[] key, Int32 dwFlags)
at System.Security.Cryptography.RSACryptoServiceProvider.Decrypt(Byte[] rgb, Boolean fOAEP)
at TestDecryption.MyDecryptor.DecryptDocIDWithFileCert(String pfxFilePath, Byte[] EncryptedDocID) in C:\Users\developmentUser\Documents\Visual Studio 2008\Projects\TestDecryption\TestDecryption\MyDecryptor.cs:line 71
at TestDecryption.Program.Main(String[] args) in C:\Users\developmentUser\Documents\Visual Studio 2008\Projects\TestDecryption\TestDecryption\Program.cs:line 37
取决于我通过 makeCert ( -pe )设置的标志
我的新问题是:
SQL-Server 是否使用 RSA 使用 ENCRYPTBYCERT() 加密数据????????????? 还是我在尝试不可行?
是的,好像是用RSA加密的。Michael Coles正在制作一些非常相似的东西,并使用 RsaCryptoServiceProvider 在他的 .NET 应用程序中加密数据。但他使用存储过程来解密数据。我不想解密服务器上的数据。我还需要用 RsaCryptoServiceProvider 解密它。
所以新的标题应该是:我怎样才能摆脱我的错误?
更新: 如何使用 RsaCryptoServiceProvider 和自制证书解密数据?