使用DPAPI加密或解密你的数据
生活随笔
收集整理的這篇文章主要介紹了
使用DPAPI加密或解密你的数据
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
對于小量數據的加密,我們可以使用DPAPI,對稱密鑰,非對稱密鑰等。
對于大量數據的加密,非對稱密鑰加密不僅麻煩,而且速度也很慢,同時還要對公鑰和密鑰進行保密。
使用對稱密鑰,速度是相當快的,但仍然要處理密鑰的問題,當然這種密鑰也有時效性,因為它容易被破解。所出一般情況下用于網絡上的會話傳輸,SSL中用的較多。
對于不想保存密鑰,而又要加密和解密來說,DPAPI可能顯得簡單的多,而且也不需要自己寫太多的代碼,安全性也得到一定的保證,同時不需要保存密鑰,一舉多得。
使用舉例,下面就DPAPI加密和解密數據庫連接字符串舉例:
2DataProtector?dataProtector?=?new?DataProtector(DataProtector.Store.USE_MACHINE_STORE);
3byte[]?bts?=??Encoding.Default.GetBytes(dbconn);
4byte[]?bytes?=?dataProtector.Encrypt(bts,?null);//加密
5string?values?=?Encoding.Default.GetString(dataProtector.Decrypt(bytes,?null));//解密
6
下面是對DPAPI的封裝。
??1using?System;??2using?System.Runtime.InteropServices;
??3
??4namespace?CNetware.Data.DPAPI
??5{
??6??/**////?<summary>
??7??///?DataProtector?是使用?DPAPI?來加密和解密數據的托管庫。
??8??///?Web?應用程序經常需要在應用程序配置文件中存儲與安全性密切相關的數據,
??9??///?如數據庫連接字符串和服務帳戶憑據。出于安全性考慮,決不要以明文形式存
?10??///?儲此類信息,而一定要在存儲之前進行加密。本類是一個托管類庫,它用于封裝
?11??///?對數據保護?API?(DPAPI)?的調用以使用基于計算機或用戶的密鑰存儲來加密和
?12??///?解密數據??呻S后從其他托管應用程序使用該庫,如?ASP.NET?Web?應用程序、Web
?13??///?服務以及企業服務應用程序。??
?14??///?DPAPI?是加密?API?(Crypto?API)?的一部分并且是在?crypt32.dll?中實現的。它
?15??///?包含兩個方法:CryptProtectData?和?CryptUnprotectData,本類庫中方法被引用
?16??///?成了私有方法,在類外不可訪問。
?17??///?DPAPI?特別有用,因為它能夠消除使用密碼的應用程序所帶來的密鑰管理問題。雖
?18??///?然加密能確保數據安全,但您必須采取額外的步驟來確保密鑰的安全。DPAPI?使用
?19??///?與?DPAPI?函數的調用代碼關聯的用戶帳戶的密碼,以便派生加密密鑰。因此,是
?20??///?操作系統(而非應用程序)管理著密鑰。
?21??///?
?22??///?DPAPI?能夠與計算機存儲或用戶存儲(需要一個已加載的用戶配置文件)配合使用。
?23??///?DPAPI?默認情況下用于用戶存儲,但您可以通過將?CRYPTPROTECT_LOCAL_MACHINE?
?24??///?標志傳遞給?DPAPI?函數來指定使用計算機存儲。
?25??///?
?26??///?這種用戶配置文件方式提供了一個額外的安全層,因為它限制了哪些用戶能訪問機
?27??///?密內容。只有加密該數據的用戶才能解密該數據。但是,當通過?ASP.NET?Web?應用
?28??///?程序使用?DPAPI?時,使用用戶配置文件需要您執行額外的開發工作,因為您需要采
?29??///?取明確的步驟來加載和卸載用戶配置文件(ASP.NET?不會自動加載用戶配置文件)。
?30??///?
?31??///?計算機存儲方式更容易開發,因為它不需要管理用戶配置文件。但是,除非使用一個
?32??///?附加的熵參數,否則并不安全,因為該計算機的任何用戶都可以解密數據。(熵是一
?33??///?個設計用來使解密機密內容更為困難的隨機值)。使用附加的熵參數出現的問題在于
?34??///?它必須由應用程序安全地存儲起來,這帶來了另一個密鑰管理問題。
?35??///?
?36??///?注意:如果您將?DPAPI?和計算機存儲一起使用,那么加密字符串僅適用于給定的計
?37??///?算機,因此您必須在每臺計算機上生成加密數據。不要在場或群集中將加密數據從一
?38??///?臺計算機復制到另一臺計算機。如果將?DPAPI?和用戶存儲一起使用,則可以用一個漫
?39??///?游的用戶配置文件在任何一臺計算機上解密數據。
?40??///?</summary>
?41??public?class?DataProtector
?42??{
?43????/**////?<summary>
?44????///?用于存儲二進制數據流,該結構體有兩個成員
?45????///?</summary>
?46????[StructLayout(LayoutKind.Sequential,?CharSet=CharSet.Unicode)]
?47??????internal?struct?DATA_BLOB
?48????{
?49??????/**////?<summary>
?50??????///?用于記錄數據長度
?51??????///?</summary>
?52??????public?int?cbData;
?53??????/**////?<summary>
?54??????///?用于存儲二進制數據
?55??????///?</summary>
?56??????public?IntPtr?pbData;
?57????}
?58????/**////?<summary>
?59????///?
?60????///?</summary>
?61????[StructLayout(LayoutKind.Sequential,?CharSet=CharSet.Unicode)]
?62??????internal?struct?CRYPTPROTECT_PROMPTSTRUCT
?63????{
?64??????public?int?cbSize;
?65??????public?int?dwPromptFlags;
?66??????public?IntPtr?hwndApp;
?67??????public?String?szPrompt;
?68????}
?69????private?static??IntPtr?NullPtr?=?(IntPtr)0;
?70
?71????private?const?int?CRYPTPROTECT_UI_FORBIDDEN?=?0x1;
?72
?73????private?const?int?CRYPTPROTECT_LOCAL_MACHINE?=?0x4;
?74
?75????/**////?<summary>
?76????///?
?77????///?</summary>
?78????///?<param?name="pDataIn"></param>
?79????///?<param?name="szDataDescr"></param>
?80????///?<param?name="pOptionalEntropy"></param>
?81????///?<param?name="pvReserved"></param>
?82????///?<param?name="pPromptStruct"></param>
?83????///?<param?name="dwFlags"></param>
?84????///?<param?name="pDataOut"></param>
?85????///?<returns></returns>
?86????[DllImport("Crypt32.dll",?SetLastError=true,
?87???????CharSet=System.Runtime.InteropServices.CharSet.Auto)]
?88????private?static?extern?bool?CryptProtectData(
?89??????ref?DATA_BLOB?pDataIn,
?90??????String?szDataDescr,
?91??????ref?DATA_BLOB?pOptionalEntropy,
?92??????IntPtr?pvReserved,
?93??????ref?CRYPTPROTECT_PROMPTSTRUCT?pPromptStruct,
?94??????int?dwFlags,
?95??????ref?DATA_BLOB?pDataOut);
?96
?97????/**////?<summary>
?98????///?
?99????///?</summary>
100????///?<param?name="pDataIn"></param>
101????///?<param?name="szDataDescr"></param>
102????///?<param?name="pOptionalEntropy"></param>
103????///?<param?name="pvReserved"></param>
104????///?<param?name="pPromptStruct"></param>
105????///?<param?name="dwFlags"></param>
106????///?<param?name="pDataOut"></param>
107????///?<returns></returns>
108????[DllImport("Crypt32.dll",?SetLastError=true,
109???????CharSet=System.Runtime.InteropServices.CharSet.Auto)]
110????private?static?extern?bool?CryptUnprotectData(
111??????ref?DATA_BLOB?pDataIn,
112??????String?szDataDescr,
113??????ref?DATA_BLOB?pOptionalEntropy,
114??????IntPtr?pvReserved,
115??????ref?CRYPTPROTECT_PROMPTSTRUCT?pPromptStruct,
116??????int?dwFlags,
117??????ref?DATA_BLOB?pDataOut);
118
119????[DllImport("kernel32.dll",
120???????CharSet=System.Runtime.InteropServices.CharSet.Auto)]
121????private?unsafe?static?extern?int?FormatMessage(int?dwFlags,
122??????ref?IntPtr?lpSource,
123??????int?dwMessageId,
124??????int?dwLanguageId,
125??????ref?String?lpBuffer,?
126??????int?nSize,
127??????IntPtr?*Arguments);
128
129????/**////?<summary>
130????///?用于指定創建DataProtector的類型
131????///?</summary>
132????public?enum?Store?
133????{
134??????/**////?<summary>
135??????///?機器存儲
136??????///?</summary>
137??????USE_MACHINE_STORE?=?1,?
138
139??????/**////?<summary>
140??????///?用戶自己存儲
141??????///?</summary>
142??????USE_USER_STORE
143????};
144
145????/**////?<summary>
146????///?
147????///?</summary>
148????private?Store?m_store;
149
150????/**////?<summary>
151????///?創建數據保護對象,該對象可能指定數據和處理方法。
152????///?</summary>
153????///?<param?name="store">存儲類型</param>
154????public?DataProtector(Store?store)
155????{
156??????m_store?=?store;
157????}
158
159????/**////?<summary>
160????///?對傳入的文本信息進行加密處理,并以字節流方式返回
161????///?</summary>
162????///?<param?name="plainText">被字節化的文本</param>
163????///?<param?name="optionalEntropy">隨機熵,可以為空,如果創建的是用戶管理的DataProtector,該選擇無效</param>
164????///?<returns>返回被加過密的內容</returns>
165????public?byte[]?Encrypt(byte[]?plainText,?byte[]?optionalEntropy)
166????{
167??????bool?retVal?=?false;
168??????DATA_BLOB?plainTextBlob?=?new?DATA_BLOB();
169??????DATA_BLOB?cipherTextBlob?=?new?DATA_BLOB();
170??????DATA_BLOB?entropyBlob?=?new?DATA_BLOB();
171??????CRYPTPROTECT_PROMPTSTRUCT?prompt?=?new?CRYPTPROTECT_PROMPTSTRUCT();
172??????InitPromptstruct(ref?prompt);
173??????int?dwFlags;
174??????try
175??????{
176????????try
177????????{
178??????????int?bytesSize?=?plainText.Length;
179??????????plainTextBlob.pbData?=?Marshal.AllocHGlobal(bytesSize);
180??????????if(IntPtr.Zero?==?plainTextBlob.pbData)
181??????????{
182????????????throw?new?Exception(Strings.ALLOC_TEXT_BUFFER_EXCEPTION);
183??????????}
184??????????plainTextBlob.cbData?=?bytesSize;
185??????????Marshal.Copy(plainText,?0,?plainTextBlob.pbData,?bytesSize);
186????????}
187????????catch(Exception?ex)
188????????{
189??????????throw?new?Exception(Strings.MERGING_EXCEPTION?+?ex.Message);
190????????}
191????????if(Store.USE_MACHINE_STORE?==?m_store)
192????????{//使用計算機存儲,應該提供熵。
193??????????dwFlags?=?CRYPTPROTECT_LOCAL_MACHINE|CRYPTPROTECT_UI_FORBIDDEN;
194??????????//查看熵是否為空
195??????????if(null?==?optionalEntropy)
196??????????{//分配對象
197????????????optionalEntropy?=?new?byte[0];
198??????????}
199??????????try
200??????????{
201????????????int?bytesSize?=?optionalEntropy.Length;
202????????????entropyBlob.pbData?=?Marshal.AllocHGlobal(optionalEntropy
203??????????????.Length);;
204????????????if(IntPtr.Zero?==?entropyBlob.pbData)
205????????????{
206??????????????throw?new?Exception(Strings.CANNOT_ALLOC_BUFFER_FOR_ENTROPY);
207????????????}
208????????????Marshal.Copy(optionalEntropy,?0,?entropyBlob.pbData,?bytesSize);
209????????????entropyBlob.cbData?=?bytesSize;
210??????????}
211??????????catch(Exception?ex)
212??????????{
213????????????
214????????????throw?new?Exception(Strings.ENTROPY_MERGING_EXCEPTION?+
215??????????????ex.Message);
216??????????}
217????????}
218????????else
219????????{//使用用戶存儲
220??????????dwFlags?=?CRYPTPROTECT_UI_FORBIDDEN;
221????????}
222????????retVal?=?CryptProtectData(ref?plainTextBlob,?"",?ref?entropyBlob,
223??????????IntPtr.Zero,?ref?prompt,?dwFlags,
224??????????ref?cipherTextBlob);
225????????if(false?==?retVal)
226????????{
227??????????throw?new?Exception(Strings.ENCRYPT_FAILED?+
228????????????GetErrorMessage(Marshal.GetLastWin32Error()));
229????????}
230??????}
231??????catch(Exception?ex)
232??????{
233????????throw?new?Exception(Strings.ENCRYPT_EXCEPTION?+?ex.Message);
234??????}
235??????byte[]?cipherText?=?new?byte[cipherTextBlob.cbData];
236??????Marshal.Copy(cipherTextBlob.pbData,?cipherText,?0,?cipherTextBlob.cbData);
237??????return?cipherText;
238????}
239
240????/**////?<summary>
241????///?對已經加過密的數據進行解密
242????///?</summary>
243????///?<param?name="cipherText">密文</param>
244????///?<param?name="optionalEntropy">隨機熵</param>
245????///?<returns>返回解密后的明文</returns>
246????public?byte[]?Decrypt(byte[]?cipherText,?byte[]?optionalEntropy)
247????{
248??????bool?retVal?=?false;
249??????DATA_BLOB?plainTextBlob?=?new?DATA_BLOB();
250??????DATA_BLOB?cipherBlob?=?new?DATA_BLOB();
251??????CRYPTPROTECT_PROMPTSTRUCT?prompt?=?new?CRYPTPROTECT_PROMPTSTRUCT();
252??????InitPromptstruct(ref?prompt);
253??????try
254??????{
255????????try
256????????{
257??????????int?cipherTextSize?=?cipherText.Length;
258??????????cipherBlob.pbData?=?Marshal.AllocHGlobal(cipherTextSize);
259??????????if(IntPtr.Zero?==?cipherBlob.pbData)
260??????????{
261????????????throw?new?Exception(String.Format(Strings.ALLOC_BUFFER_FAILED,"cipherBlob"));
262??????????}
263??????????cipherBlob.cbData?=?cipherTextSize;
264??????????Marshal.Copy(cipherText,?0,?cipherBlob.pbData,?cipherBlob.cbData);
265????????}
266????????catch(Exception?ex)
267????????{
268??????????throw?new?Exception(Strings.MERGING_EXCEPTION?+?ex.Message);
269????????}
270????????DATA_BLOB?entropyBlob?=?new?DATA_BLOB();
271????????int?dwFlags;
272????????if(Store.USE_MACHINE_STORE?==?m_store)
273????????{//使用計算機存儲,應該提供熵。
274??????????dwFlags?=?CRYPTPROTECT_LOCAL_MACHINE|CRYPTPROTECT_UI_FORBIDDEN;
275??????????//查看熵是否為空
276??????????if(null?==?optionalEntropy)
277??????????{//分配對象
278????????????optionalEntropy?=?new?byte[0];
279??????????}
280??????????try
281??????????{
282????????????int?bytesSize?=?optionalEntropy.Length;
283????????????entropyBlob.pbData?=?Marshal.AllocHGlobal(bytesSize);
284????????????if(IntPtr.Zero?==?entropyBlob.pbData)
285????????????{
286??????????????throw?new?Exception(String.Format(Strings.ALLOC_BUFFER_FAILED,"熵"));
287????????????}
288????????????entropyBlob.cbData?=?bytesSize;
289????????????Marshal.Copy(optionalEntropy,?0,?entropyBlob.pbData,?bytesSize);
290??????????}
291??????????catch(Exception?ex)
292??????????{
293????????????throw?new?Exception("Entropy(熵)"+Strings.MERGING_EXCEPTION?+ex.Message);
294??????????}
295????????}
296????????else
297????????{//使用用戶存儲
298??????????dwFlags?=?CRYPTPROTECT_UI_FORBIDDEN;
299????????}
300????????retVal?=?CryptUnprotectData(ref?cipherBlob,?null,?ref?entropyBlob,
301??????????IntPtr.Zero,?ref?prompt,?dwFlags,
302??????????ref?plainTextBlob);
303????????if(false?==?retVal)
304????????{
305??????????throw?new?Exception(Strings.DECRYPT_FAILED?+
306????????????GetErrorMessage(Marshal.GetLastWin32Error()));
307????????}
308????????//釋放?blob?和熵。
309????????if(IntPtr.Zero?!=?cipherBlob.pbData)
310????????{
311??????????Marshal.FreeHGlobal(cipherBlob.pbData);
312????????}
313????????if(IntPtr.Zero?!=?entropyBlob.pbData)
314????????{
315??????????Marshal.FreeHGlobal(entropyBlob.pbData);
316????????}
317??????}
318??????catch(Exception?ex)
319??????{
320????????throw?new?Exception(Strings.DECRYPT_EXCEPTION?+?ex.Message);
321??????}
322??????byte[]?plainText?=?new?byte[plainTextBlob.cbData];
323??????Marshal.Copy(plainTextBlob.pbData,?plainText,?0,?plainTextBlob.cbData);
324??????return?plainText;
325????}
326
327????/**////?<summary>
328????///?
329????///?</summary>
330????///?<param?name="ps"></param>
331????private?void?InitPromptstruct(ref?CRYPTPROTECT_PROMPTSTRUCT?ps)
332????{
333??????ps.cbSize?=?Marshal.SizeOf(typeof(CRYPTPROTECT_PROMPTSTRUCT));
334??????ps.dwPromptFlags?=?0;
335??????ps.hwndApp?=?NullPtr;
336??????ps.szPrompt?=?null;
337????}
338
339????/**////?<summary>
340????///?
341????///?</summary>
342????///?<param?name="errorCode"></param>
343????///?<returns></returns>
344????private?unsafe?static?String?GetErrorMessage(int?errorCode)
345????{
346??????int?FORMAT_MESSAGE_ALLOCATE_BUFFER?=?0x00000100;
347??????int?FORMAT_MESSAGE_IGNORE_INSERTS?=?0x00000200;
348??????int?FORMAT_MESSAGE_FROM_SYSTEM?=?0x00001000;
349??????int?messageSize?=?255;
350??????String?lpMsgBuf?=?"";
351??????int?dwFlags?=?FORMAT_MESSAGE_ALLOCATE_BUFFER?|
352????????FORMAT_MESSAGE_FROM_SYSTEM?|
353????????FORMAT_MESSAGE_IGNORE_INSERTS;
354??????IntPtr?ptrlpSource?=?new?IntPtr();
355??????IntPtr?prtArguments?=?new?IntPtr();
356??????int?retVal?=?FormatMessage(dwFlags,?ref?ptrlpSource,?errorCode,?0,
357????????ref?lpMsgBuf,?messageSize,?&
358????????prtArguments);
359??????if(0?==?retVal)
360??????{
361????????throw?new?Exception(Strings.SET_ERROR_MSG_FAILED?+?errorCode?+?"。");
362??????}
363??????return?lpMsgBuf;
364????}
365??}
366??internal?class?Strings
367??{
368????private?Strings()
369????{
370????}
371????internal?static?string?ENTROPY_MERGING_EXCEPTION????="熵整理數據時發生異常。";
372????internal?static?string?MERGING_EXCEPTION????????="整理數據時發生異常。";
373????internal?static?string?CANNOT_ALLOC_BUFFER_FOR_ENTROPY??="無法分配熵數據緩沖區。";
374????internal?static?string?ALLOC_TEXT_BUFFER_EXCEPTION????="無法分配純文本緩沖區。";
375????internal?static?string?ALLOC_BUFFER_FAILED????????="為{0}分配緩存區失敗。";
376????internal?static?string?ENCRYPT_FAILED?????????="加密失敗。";
377????internal?static?string?DECRYPT_FAILED?????????="解密失敗。";
378????internal?static?string?ENCRYPT_EXCEPTION????????="加密時發生異常。";
379????internal?static?string?DECRYPT_EXCEPTION????????="解密時發生異常。";
380????internal?static?string?SET_ERROR_MSG_FAILED???????="無法設置錯誤代碼消息的格式。";
381????internal?static?string?NOT_RIGHT_CONFIGPATH???????="不正確的配置文件路徑。";
382????internal?static?string?CONFIG_PATH_NOT_SETTED?????="配置文件的全路徑未設置。";
383????internal?static?string?NOT_FOUND_CONNECTION_STRING????="沒有發現配置文件中有此文件。";
384????internal?static?string?CONN_STRING_NAMED_EXCEPTION????="配置文件中定義的數據庫連接字符串的key的名字應當以ConnectionString打頭。";
385??}
386}
387
388
轉載于:https://www.cnblogs.com/begincsdn/archive/2005/07/13/191987.html
總結
以上是生活随笔為你收集整理的使用DPAPI加密或解密你的数据的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: javascript写的关于静态页面获取
- 下一篇: 一起进步