Windows Phone应用程序中加密解密数据

     在程序中加密解密是我们常要用到的功能,比如对密码,数据库连接字符串,PIN等的加密。虽然Windows Phone限制了应用程序仅能访问自己的独立存储,但是将重要数据以明文的形式存储在Isolated Storage依然是不安全的。在Windows Phone中加密解密通过Data Protection API (DPAPI)来实现。如果对加密解密有所了解的朋友会清楚,非对称的加密我们需要用到密钥对,而这往往需要我们自己生成,同时密钥本身需要存储,或者通过第三方机构颁布证书等的方式来验证信息的可靠性。而Windows Phone为我们简化了这个难题,每一个程序在第一次运行的时候就可以获得它自己的解密密钥。而我们只需要借助 ProtectedData 类的 Protect Unprotect 方法分别实现加密和解密。对于数据类型的文件,直接可以对数据库加密,在连接字符串中使用Password参数即可。当然连接字符串本身也需要进行加密和解密,以防止密码泄露。

    
接下来我将演示如何在Windows Phone 应用程序中运用这两个方法。本文请参考MSDN文档 http://msdn.microsoft.com/zh-cn/library/hh487164(v=VS.92).aspx

创建项目                                   

1.   创建Windows Phone 7项目EncryptionAndDecryptionWP

2.   添加TextBox控件txtData

3.   添加btnStore按钮,用于加密数据,将加密结果保存在内存中

4.   添加btnRetrieve按钮,用于解密数据,并将解密结果用弹出对话框显示。


ContentPanel 部分的 XAML 如下 :
< Grid  x:Name ="LayoutRoot"  Background ="Transparent" >
         < Grid  x:Name ="ContentPanel"  Grid.Row ="1"  Margin ="12,150,12,0" >
             < StackPanel  Orientation ="Vertical" >
                 < TextBox  x:Name ="txtData"  Height ="80"  Width ="460"  Foreground =" {StaticResource PhoneAccentBrush} "  FontSize =" {StaticResource PhoneFontSizeLarge} "   />
                 < Button  x:Name ="btnStore"  Content ="Store"  Height ="71"  Width ="160"  BorderBrush =" {StaticResource PhoneAccentBrush} "  Foreground =" {StaticResource PhoneAccentBrush} "  Click ="btnStore_Click"   />
                 < Button  x:Name ="btnRetrieve"  Content ="Retrieve"  Height ="71"  Width ="160"  BorderBrush =" {StaticResource PhoneAccentBrush} "  Foreground =" {StaticResource PhoneAccentBrush} "  Click ="btnRetrieve_Click"   />
             </ StackPanel >
         </ Grid >
     </ Grid >

 

加密数据                                   
当单击btnStore后,加密txtData中的数据,并保存在变量中,代码如下:

private  byte[] _encryptedBytes;

private  void btnStore_Click( object sender, RoutedEventArgs e)
{
       var sourceBytes = Encoding.UTF8.GetBytes(txtData.Text.Trim());
      _encryptedBytes = ProtectedData.Protect(sourceBytes,  null); 
}

解密数据                                       

当单击btnRetrieve后,解密数据,代码如下:

  private  void btnRetrieve_Click( object sender, RoutedEventArgs e)
 {
       if (_encryptedBytes ==  nullreturn;
       var bytes = ProtectedData.Unprotect(_encryptedBytes,  null);
       if (bytes !=  null) MessageBox.Show(Encoding.UTF8.GetString(bytes,  0, bytes.Length)); 
  }

 
运行结果:输入admin

Windows Phone应用程序中加密解密数据Windows Phone应用程序中加密解密数据


其它说明:通常情况下,我们需要将加密后的数据保存在独立存储中;ProtectUnprotect的第二个参数是信息熵,可以增加加密的复杂度,可以均为null,同时必须保持一致。


关于WP7平台的安全策略,可以参考MSDNWindows Phone 安全性

其支持的加密算法包括:AESHMACSHA1HMACSHA256Rfc2898DeriveBytesRSASHA1SHA256

还可以参考codeplex上的开源项目:Scrypt RSA Cryptography for Silverlight 3+ and Windows Phone 7

另:.NET Framework中的AES加密通过AesManaged类来操作的,下面的程序使用此类和Rfc2898DeriveBytes类对资料进行加密

代码如下:

    // 注意AES是一个对称加密算法,用来加密和解密数据的密码和salt值必须相同
     public  class AESEncryption
    {
         ///   <summary>
        
///  加密数据
        
///   </summary>
        
///   <param name="dataToEncrypt"> 要加密的字符串 </param>
        
///   <param name="password"> 密码 </param>
        
///   <param name="salt"> salt值 </param>
        
///   <returns></returns>
         public  static  string Encrypt( string dataToEncrypt,  string password,  string salt)
        {
            AesManaged aes =  null;
            MemoryStream stream =  null;
            CryptoStream cryptoStream =  null;
             try
            {
                Rfc2898DeriveBytes rfc2898 =  new Rfc2898DeriveBytes(password, Encoding.UTF8.GetBytes(salt));
                aes =  new AesManaged();
                aes.Key = rfc2898.GetBytes(aes.KeySize /  8); // 设置用于对称算法的密钥
                aes.IV = rfc2898.GetBytes(aes.BlockSize /  8); // 设置用于对称算法的初始化向量(IV)
                stream =  new MemoryStream();
                 // 使用当前的密钥和初始化向量(IV)创建对称加密器对象
                cryptoStream =  new CryptoStream(stream, aes.CreateEncryptor(), CryptoStreamMode.Write);
                 byte[] data = Encoding.UTF8.GetBytes(dataToEncrypt);
                cryptoStream.Write(data,  0, data.Length);
                cryptoStream.FlushFinalBlock();
                 return Convert.ToBase64String(stream.ToArray());
            }
             finally
            {
                 // 关闭当前流并释放与当前流相关的任何资源
                 if (cryptoStream !=  null){
                    cryptoStream.Close();
                }
                 if (stream !=  null){
                    stream.Close();
                }
                 if (aes !=  null){
                     // 释放资源
                    aes.Clear();
                }
            }
        }

       
         ///   <summary>
        
///   解密数据
        
///   </summary>
        
///   <param name="dataToDecrypt"> 需要解密的数据 </param>
        
///   <param name="password"> 密码 </param>
        
///   <param name="salt"> salt值 </param>
        
///   <returns></returns>
         public  static  string Decrypt( string dataToDecrypt, string password, string salt)
        {
            AesManaged aes =  null;
            MemoryStream stream =  null;
            CryptoStream cryptoStream =  null;
             try
            {
                Rfc2898DeriveBytes rfc2898 =  new Rfc2898DeriveBytes(password, Encoding.UTF8.GetBytes(salt));
                aes =  new AesManaged();
                aes.Key = rfc2898.GetBytes(aes.KeySize /  8); // 设置用于对称算法的密钥
                aes.IV = rfc2898.GetBytes(aes.BlockSize /  8); // 设置用于对称算法的初始化向量(IV)
                stream =  new MemoryStream();
                 // 使用当前的密钥和初始化向量(IV)创建对称解密器对象
                cryptoStream =  new CryptoStream(stream, aes.CreateDecryptor(), CryptoStreamMode.Write);
                 byte[] data = Encoding.UTF8.GetBytes(dataToDecrypt);
                cryptoStream.Write(data,  0, data.Length);
                cryptoStream.FlushFinalBlock();

                 byte[] decryptBytes = stream.ToArray();
                 return Encoding.UTF8.GetString(decryptBytes,  0, decryptBytes.Length);
            }
             finally
            {
                 // 关闭当前流并释放与当前流相关的任何资源
                 if (cryptoStream !=  null)
                {
                    cryptoStream.Close();
                }
                 if (stream !=  null)
                {
                    stream.Close();
                }
                 if (aes !=  null)
                {
                     // 释放资源
                    aes.Clear();
                }
            }
        }
    }

 

参考:http://kosmisch.net/archive/2011/10/25/encrypt_data_in_windows_phone_application.aspx

你可能感兴趣的:(windows phone)