文档结构  
翻译进度:已翻译     翻译赏金:0 元 (?)    ¥ 我要打赏
来源: https://github.com/Pavel-Durov/CodeProject-Android-and-NET-Encryption
源码下载:

前言

可能被非法用户看到的敏感数据应该被加密。

哪些是敏感数据由你决定,可以是个人资料、在网路中传输的图片,你的地理位置等等。

敏感数据是易于泄漏的,当它在程序中被暴漏时,在网络中传输时,或者存储在本地文件时。

这篇文章不是关于安全的,仅仅介绍简单的加解密实现。

 

第 1 段(可获 1.15 积分)

什么是加密?

加密是将一段明文转换成密文。

解密是相反的,是将密文转换成可读的明文。

加密算法可以被分为两种,对称和非对称。两者都有优点和缺点。

对称加密

用一个相同的共享密钥执行加密和解密。密钥在发送和接受者之间共享。

为了对消息进行加密,发送者使用共享密钥;接收方必须使用相同的密钥来解密消息。

第 2 段(可获 1.19 积分)

对称算法非常快,但它需要双方有一个特定的、相同的密钥,这在大系统中会是一个问题,因为涉及到大量的密钥管理。

非对称加密(公钥密码体制)

消息发送者和接受者使用不同的密钥对消息进行加密和解密,每一方都有一对密钥,公钥和私钥。

当发送者要加密消息时,他使用发送者公钥。接受者可以使用他的私钥对消息进行解密。这种方法相对较慢,但在大型系统中,密钥管理更容易。

第 3 段(可获 1.24 积分)

安卓中的对称加密

在这个例子中我们将使用Android的SDK中的类cipher来实现我们加密/解密的目的。

Cipher类提供了进行加密和解密的密钥的实现。查看更多信息:

http://developer.android.com/reference/javax/crypto/Cipher.html

 

CryptoHandler 类

Cipher 取决于两个键,第一个是作为字符串传递给构造函数的密钥,第二个是原始密钥,它是16字节长的。

CryptoHandler使用实例。

<a name="CryptoHandlerClass">
//CryptoHandler构造方法
 public CryptoHandler(String passphrase)

 {
     //将加密信息转换为字节数组
     byte[] passwordKey = encodeDigest(passphrase);
     try
     {
       //_aesCipher得到特定加密算法实例
         _aesCipher = Cipher.getInstance(CIPHER_TRANSFORMATION);
     }
     catch (NoSuchAlgorithmException e)
     { //传入了非法的加密算法
         Log.e(TAG, "No such algorithm " + CIPHER_ALGORITHM, e);
     }

     catch (NoSuchPaddingException e)
     { //在传递的转换参数中有无效填充
         Log.e(TAG, "No such padding PKCS5", e);
     }


     //将传递的密码语句编码为一个字节数组
     //它将存储为SecretKey 类的私有成员
     _secretKey = new SecretKeySpec(passwordKey, CIPHER_ALGORITHM);

     //创建一个新的ivparameterspec实例,使用初始向量iv
     _ivParameterSpec = new IvParameterSpec(rawSecretKey);

 }</a>
第 4 段(可获 1.01 积分)

CryptoHandler 中我们使用AES (Advanced Encryption Standard) 算法加密,你可以在这里阅读更多信息:

http://en.wikipedia.org/wiki/Advanced_Encryption_Standard

在下面这行代码中AES实例化:

private static String CIPHER_TRANSFORMATION = "AES/CBC/PKCS5Padding";

_aesCipher = Cipher.getInstance(CIPHER_TRANSFORMATION);

我们调用了 Cipher的静态方法,它将返回一个实例化的 Cipher对象(如果没有异常被抛出)。

“AES/CBC/PKCS5Padding “(被传递的字符串转换参数)

 

AES – 加密算法 (Advanced Encryption Standard).

第 5 段(可获 0.84 积分)

CBC – 反馈模式的名称(在我们的例子中是密码块链接)。

PKCS5Padding – 填充语法名称。

 

CryptoHandler 类的方法

 

除了构造函数,我们在CryptoHandler类中还有3个其他方法:

<a name="CryptoHandlerClassMethods">
public byte[] Encrypt(byte[] clearData)</a>

Encrypt 加密方法通过将Cipher.ENCRYPT_MODE常量传递给init()方法将_aesCipher设置为加密模式。

<a name="CryptoHandlerClassMethods">
public byte[] Decrypt(byte[] data)</a>

Decrypt解密方法也是这样,但不是传递Cipher.ENCRYPT_MODE 而是传递Cipher.DECRYPT_MODE

第 6 段(可获 0.91 积分)

解密加密方法都调用DoWork()方法,它们之间的唯一区别是每个设置不同的Cipher 密码模式常数。

<a name="CryptoHandlerClassMethods">
public byte[] DoWork(byte[] data)</a>

调用_aesCipher.doFinal(数据)方法并捕获异常。

<a name="CryptoHandlerClassMethods">
private byte[] encodeDigest(String text)</a>

在构造函数中使用一次以进行密码短语编码。

私有原始密钥作为字节数组存储在类中:

<a name="CryptoHandlerClassMethods">
 private static byte[] _rawSecretKey =

 {
       0x12, 0x00, 0x22, 0x55, 0x33, 0x78, 0x25, 0x11,
       0x33, 0x45, 0x00, 0x00, 0x34, 0x00, 0x23, 0x28
 };</a>
第 7 段(可获 0.59 积分)

密钥必须在发送者和接受者之间共享,在我们的例子中,我们同时作为消息发送和接收者,所以我们使用的是同一个密钥实例进行加密和解密。

Android 实现

MainActivity布局文件,你可以看到两个颜色的区域,蓝色的供你输入文本进行加密,绿色的用来显示加密后的串。

当你按下加密按钮,加密的数据将被保存到内部文件系统(你可以在文件夹中看到它),并且在绿色块中展示出来,如图中所示乱码(它是原明文的密文)。

第 8 段(可获 1.31 积分)

*保存的数据将覆盖前面的,不会被追加到文件中的已有数据的后面。

<a name="AndroidImplementation">
/**
 *
 * 加密在_tvmessage EditText中输入的字符串值
 * 并且保存在本地文件系统中
 * 
 * */
private void EncryptMessage()
{
     String message  = _tvMessage.getText().toString();
     if(message != null && message.length() > 0)
     {
          //执行文本加密
          byte[] bytes = _crypto.Encrypt(message.getBytes());
          //设置视图的值
          SetTextViewEncryptresult(bytes);

          //保存密文到文件系统中
          _streamHandler.SaveTextFile
              (
                     FileStreamHandler.ENCRYPTED_TXT_FILENAME,
                     bytes
              );

     }     
}</a>
第 9 段(可获 0.23 积分)

*如果你不知道如何查看你的安卓设备的内部文件,查看我的文章:

http://www.codeproject.com/Articles/825304/Accessing-internal-data-on-Android-device

 

所有文件操作是通过handlers包中的FileStreamHandler处理的。

下面有几个方法负责读和写一个安卓内部存储。

当你点击在MainActivity布局中的“解密”按钮,信息会从保存的文件中读取出来,展示在你的Toast 提示中。

 

/**
 * 读取保存在本地文件的内容并解密 
 * 调用ShowToast()方法
 * */

private void DecryptMessage()

{
       byte[] fileContent = _streamHandler

              .ReadFromLocalFile(FileStreamHandler.ENCRYPTED_TXT_FILENAME);            

       if(fileContent != null && fileContent.length > 0)
       {
              //执行文件内容解密
              byte[] decrypted = _crypto.Decrypt(fileContent);
             
              //将传递的字节数组通过utf8编码创建新的字符串实例
              String readableData = StringHandler.GetString(decrypted);
              String encrypted = StringHandler.GetString(fileContent);

              if(readableData != null && encrypted != null)
              {
                     //显示提示
                     ShowToast
                     (     
                           getString(R.string.msg_decrypted) + readableData,
                           getString(R.string.msg_encrypted) + encrypted

                     );
              }
       }
       else
       {      //如果文件不存在或文件内容是空的
              ShowToast(":(", "!");
       }
}
第 10 段(可获 0.89 积分)

如果你点击了“解密”按钮,你将得到如下结果:

那意味着你完成整个加解密过程。

你输入一段文本,文本将会被加密成密文,并保存到本地文件,稍后被读取并解密为正常可读的文本。

在这个例子中我们使用java类硬编码的值简单的保存密钥和密码信息,但是这不是一个最佳的解决方案,因为它可以很容易地利用逆向工程进行查看,所以记住这件事,将钥匙放在安全的地方。

 

第 11 段(可获 1.2 积分)

在.NET上解密Android消息

现在我们将看到如何使用C#语言在.NET上解密在Android设备上加密的密文。这也可以在其他平台上完成,因为我们使用标准加密。

我们将我们以前在Android设备上保存的文件拖到机器上,并将其导入Visual Studio上的基本控制台应用程序。

好了,让我们创建文件,并使用adb拖出文件:

步骤:

  1. 在蓝色区域中输入消息,然后按加密Encrypt 按钮。

现在我们的消息被加密并保存到硬盘上。

     2. 接下来,我们将运行几个命令授予文件权限,并使用pull命令从设备获取文件。

第 12 段(可获 1.53 积分)

*再次声明,如果你不明白,请看看我的文章--关于adb工具和Android内部文件的权限:

http://www.codeproject.com/Articles/825304/Accessing-internal-data-on-Android-device

由于我所有的adb命令都执行成功,我现在可以在"下载"目录中浏览我的文件:

现在我们要将它导入到我们的.NET控制台应用程序。

*不要复制文本,我们在这里处理二进制数据,把它作为字符串拷贝可能改变其值! 只需复制文件。

在我们的C#控制台应用程序中,我们得到了CryptoHandler类,它基本上与Android上的相同。 注意在.NET上,我们使用ICryptoTransform的两个实例作为解密和加密机制。 这几乎是一样的,在Android上我们使用常量,在这里我们使用RijndaelManaged.NET类的工厂方法。

第 13 段(可获 1.73 积分)

如果每一件事情都按原样运行,运行C#程序,您将看到相同的消息,与在Android设备上输入得到的提示一样:

总结

我们加密和解密我们在Android和.NET应用程序上的简单消息。 这可以作为客户端 - 服务器通信的一部分(Android作为客户端,.NET作为服务器),使用您希望加密的文本或任何其他二进制文件,除非你将需要通过网络处理数据转换,这里例子没有包含这种情况。

不要运行和加密你手中的每一份数据,特别是当你处理大型二进制文件。 这可能会降低您的应用程序效率,尤其是如果您正在保护没有人感兴趣的数据。

第 14 段(可获 1.53 积分)

文章评论