using System;
using System.Text;
using System.Globalization;
using System.Security.Cryptography;
using System.Data.SqlClient;
using System.Data;
using System.Collections.Specialized;
class DES
{
// 創(chuàng)建Key
public string GenerateKey()
{
DESCryptoServiceProvider desCrypto = (DESCryptoServiceProvider)DESCryptoServiceProvider.Create();
return ASCIIEncoding.ASCII.GetString(desCrypto.Key);
}
// 加密字符串
public string EncryptString(string sInputString, string sKey)
{
byte [] data = Encoding.UTF8.GetBytes(sInputString);
DESCryptoServiceProvider DES = new DESCryptoServiceProvider();
DES.Key = ASCIIEncoding.ASCII.GetBytes(sKey);
DES.IV = ASCIIEncoding.ASCII.GetBytes(sKey);
ICryptoTransform desencrypt = DES.CreateEncryptor();
byte [] result = desencrypt.TransformFinalBlock(data, 0, data.Length);
return BitConverter.ToString(result);
}
// 解密字符串
public string DecryptString(string sInputString, string sKey)
{
string [] sInput = sInputString.Split("-".ToCharArray());
byte [] data = new byte[sInput.Length];
for(int i = 0; i < sInput.Length; i++)
{
data[i] = byte.Parse(sInput[i], NumberStyles.HexNumber);
}
DESCryptoServiceProvider DES = new DESCryptoServiceProvider();
DES.Key = ASCIIEncoding.ASCII.GetBytes(sKey);
DES.IV = ASCIIEncoding.ASCII.GetBytes(sKey);
ICryptoTransform desencrypt = DES.CreateDecryptor();
byte [] result = desencrypt.TransformFinalBlock(data, 0, data.Length);
return Encoding.UTF8.GetString(result);
}
}
class Test
{
static void Main(string[] args)
{
DES des = new DES();
string key = des.GenerateKey();
//
//數(shù)據(jù)加密
SqlDataAdapter sda=new SqlDataAdapter("select * from test2",con);
SqlCommandBuilder scb=new SqlCommandBuilder(sda);
DataSet ds=new DataSet();
sda.Fill(ds,"test2");
foreach (DataRow dr in ds.Tables["test2"].Rows)
{
string name=Convert.ToString(dr["userName"]);
string mName= des.EncryptString(name, key);
string pwd=Convert.ToString(dr["userPwd"]);
string mPwd= des.EncryptString(pwd, key);
string identity=Convert.ToString(dr["userIdentity"]);
string mIdentity= des.EncryptString(identity, key);
Console.WriteLine("密文:"+mName+";"+mPwd+";"+mIdentity);
dr["userName"]=Convert.ToString(mName);
dr["userPwd"]=Convert.ToString(mPwd);
dr["userIdentity"]=Convert.ToString(mIdentity);
}
//數(shù)據(jù)庫更新
sda.Update(ds,"test2");
foreach(DataRow dr in ds.Tables["test2"].Rows)
{
Console.WriteLine("數(shù)據(jù)更新為:"+dr["userName"]+" "+dr["userPwd"]+" "+dr["userIdentity"]);
}
//數(shù)據(jù)解密
SqlCommand com=new SqlCommand("select * from test2",con);
SqlDataReader sdr=com.ExecuteReader();
while(sdr.Read())
{
string name=Convert.ToString(sdr["userName"]);
string userName= des.DecryptString(name, key);
string pwd=Convert.ToString(sdr["userPwd"]);
string userPwd= des.DecryptString(pwd, key);
string identity=Convert.ToString(sdr["userIdentity"]);
string userIdentity= des.DecryptString(identity, key);
Console.WriteLine("解密:"+userName+";"+userPwd+";"+userIdentity);
}
sdr.Close();
con.Close();
}
}
SQL Server 2008 安全性——透明數(shù)據(jù)加密(TDE)
SQL Server 2008 安全性——透明數(shù)據(jù)加密(TDE)
在SQL Server 2005的安全性來說,做的不夠好,比如EKM這種可擴(kuò)展的外部密鑰管理就不支持,包括對數(shù)據(jù)庫文件本身的加密。
SQL Server 2008中增加了透明數(shù)據(jù)加密TDE,TDE使用DEK 數(shù)據(jù)庫加密密鑰對數(shù)據(jù)文件進(jìn)行加密,包括IO操作,加入內(nèi)存等都是存在加密和解密操作的。DEK本身是受master數(shù)據(jù)庫下的證書保護(hù)的,當(dāng)然也支持EKM模塊包含。我們對數(shù)據(jù)文件可以使用標(biāo)準(zhǔn)的DES 和AES加密。
在某些特定場合,比如我們的服務(wù)器發(fā)生盜竊行為的時(shí)候,一些關(guān)鍵性數(shù)據(jù)庫不被惡意附加挖掘其中的價(jià)值數(shù)據(jù),除了使用硬件級別的文件格式加密。SQL Server 用TDE來保護(hù)文件安全。
我主要通過T-SQL 腳本的形式描述 整個(gè)加密以及分離、附加數(shù)據(jù)庫的流程。
/*
Title:TDE加密
Author:浪客
Environment:Windows Server 2008 Enterprise + SQL Server 2008 Enterprise
Description:請?jiān)诜巧a(chǎn)環(huán)境下測試
*/
USE [master];
GO
--查看master數(shù)據(jù)庫是否被加密
SELECT name,is_master_key_encrypted_by_server FROM sys.databases;
--創(chuàng)建master數(shù)據(jù)庫下的主數(shù)據(jù)庫密鑰
CREATE MASTER KEY ENCRYPTION BY PASSWORD = N'浪客!@#$%^&*()0A';
--查看master數(shù)據(jù)庫下的密鑰信息
SELECT * FROM sys.symmetric_keys;
--創(chuàng)建證書用來保護(hù) 數(shù)據(jù)庫加密密鑰 (DEK)
CREATE CERTIFICATE master_server_cert WITH SUBJECT = N'Master Protect DEK Certificate';
IF DB_ID('db_encryption_test') IS NOT NULL
DROP DATABASE db_encryption_test
--創(chuàng)建測試數(shù)據(jù)庫
CREATE DATABASE db_encryption_test;
GO
USE db_encryption_test;
--創(chuàng)建由master_server_cert保護(hù)的DEK 數(shù)據(jù)庫加密密鑰 (對稱密鑰)
CREATE DATABASE ENCRYPTION KEY
WITH ALGORITHM = AES_128
ENCRYPTION BY SERVER CERTIFICATE master_server_cert;
GO
--執(zhí)行上語句以后出現(xiàn):
/*
Warning: The certificate used for encrypting the database encryption key has not been backed up. You should immediately back up the certificate and the private key associated with the certificate. If the certificate ever becomes unavailable or if you must restore or attach the database on another server, you must have backups of both the certificate and the private key or you will not be able to open the database.
*/
--提示你,立刻備份證書;這里備份證書,不比制定加密私鑰的 對稱密鑰了.因?yàn)樗拿荑€是通過master數(shù)據(jù)庫的主數(shù)據(jù)庫密鑰加密了.
USE master;
BACKUP CERTIFICATE master_server_cert TO FILE = 'D:\MSSQL\Certificate\master_server_cert.cer'
WITH PRIVATE KEY (
FILE = 'D:\MSSQL\Certificate\master_server_cert.pvk' ,
ENCRYPTION BY PASSWORD = '浪客!@#$%^&*()0A' );
--相應(yīng)的,我們也備份一下數(shù)據(jù)庫主密鑰(master)
USE master;
--如果沒有啟用主密鑰的自動解密功能
--OPEN MASTER KEY DECRYPTION BY PASSWORD = '浪客!@#$%^&*()0A';
BACKUP MASTER KEY TO FILE = 'D:\MSSQL\MasterKey\master.cer'
ENCRYPTION BY PASSWORD = '浪客!@#$%^&*()0A';
GO
--生產(chǎn)環(huán)境下,設(shè)置成單用戶在運(yùn)行加密
ALTER DATABASE db_encryption_test SET SINGLE_USER WITH ROLLBACK IMMEDIATE;
GO
--備份成功以后,開啟TDE 加密
ALTER DATABASE db_encryption_test SET ENCRYPTION ON;
GO
--設(shè)置多用戶訪問
ALTER DATABASE db_encryption_test SET MULTI_USER WITH ROLLBACK IMMEDIATE;
GO
--查看db_encryption_test數(shù)據(jù)庫是否被加密 encryption_state:3 TDE加密了
SELECT DB_NAME(database_id),encryption_state FROM sys.dm_database_encryption_keys;
/*
發(fā)現(xiàn)tempdb也被加密了。MSDN解釋是:如果實(shí)例中有一個(gè)數(shù)據(jù)庫啟用了TDE加密,那么tempdb也被加密
*/
--接下來,找另外一臺機(jī)器或者實(shí)例來測試,如果數(shù)據(jù)文件被盜走了,防止附加的測試.
USE master;
EXEC sp_detach_db N'db_encryption_test';
GO
--將文件QQ發(fā)到了另外的機(jī)器,我同事 CL .
USE master;
--我先在他機(jī)器還原了MASTER KEY (他原機(jī)器master庫無master key)
RESTORE MASTER KEY
FROM FILE = 'C:\Users\Administrator\Desktop\master.cer'
DECRYPTION BY PASSWORD = '浪客!@#$%^&*()0A'
ENCRYPTION BY PASSWORD = '浪客!@#$%^&*()0A';
GO
--如果沒有自動加密
OPEN MASTER KEY DECRYPTION BY PASSWORD=N'浪客!@#$%^&*()0A';
--創(chuàng)建證書
CREATE CERTIFICATE master_server_cert
FROM FILE = 'C:\Users\Administrator\Desktop\master_server_cert.cer'
WITH PRIVATE KEY (FILE = 'C:\Users\Administrator\Desktop\master_server_cert.pvk',
DECRYPTION BY PASSWORD = '浪客!@#$%^&*()0A');
GO
--附加數(shù)據(jù)庫
CREATE DATABASE db_encryption_test
ON PRIMARY
(
FILENAME=N'C:\Users\Administrator\Desktop\db_encryption_test.mdf'
)
LOG ON
(
FILENAME=N'C:\Users\Administrator\Desktop\db_encryption_test_log.ldf'
)
FOR ATTACH ;
GO
--測試成功,GG,GL
--關(guān)閉數(shù)據(jù)庫聯(lián)接
CLOSE MASTER KEY
通常我們使用某種新特性的時(shí)候,還會關(guān)注他對SQL Server其他組件的影響,包括復(fù)制服務(wù)以及數(shù)據(jù)庫鏡像以及日志傳送。復(fù)制是通過標(biāo)志事務(wù)日志傳送標(biāo)識日志的方式同步數(shù)據(jù),當(dāng)時(shí)通過bcp生成的快照文件,不會采用TDE加密數(shù)據(jù),這種存在傳輸信道的 我們通常使用OS的IpSec,SSL,TSL方式來加密連接,這種在以后的文章會向大家提到。而數(shù)據(jù)鏡像和日志通過傳送日志的方式,所以傳輸過程中的日志文件是加密的。
/Files/bhtfg538/MSSQL/Security/Encryption/encry_1.txt