关于Android DES加密算法在不同平台加密结果不同的问题的一个解决方法

  <span style="font-size:18px;"> 在Android开发时经常涉及到客户端与服务端的交互,对于一些敏感数据需要进行加密处理。比如登录功能的密码加密,这里介绍   DES加密的一些实现代码和注意事项。   </span>
<span style="font-size:18px;">  请原谅我匮乏表达能力,</span>如果你看不太懂,可以查看相关链接)由于不同的开发环境,在进行加密和解密的时候经常出    现结果不相同的情况,我遇到的是用Android    客户端进行DES加密,然后在服务器端用C#DES方法进行解密,结果。。。   </span>
<span style="font-size:18px;">  先看一下Android端的DES加密算法:(来自网络粘贴:原址:</span><span style="font-size:14px;">http://www.it165.net/pro/html/201411/26957.html,http://www.  it165.net/pro/html/201411/26957.html</span>
<span style="font-size:18px;">  public static final String ALGORITHM_DES = "DES/CBC/PKCS5Padding";
</span>
        public static final String ALGORITHM_DES = "DES/CBC/PKCS5Padding";
	private static byte[] IV={0x12,0x34,0x56,0x78,(byte) 0x90,(byte) 0xAB,(byte) 0xCD,(byte) 0xEF};
	/**
	 * DES算法,加密
	 * 
	 * @param data
	 *            待加密字符串
	 * @param key
	 *            加密私钥,长度不能够小于8位
	 * @return 加密后的字节数组,一般结合Base64编码使用
	 * @throws InvalidAlgorithmParameterException
	 * @throws Exception
	 */
	public static String encode(String key, String data) {
		if (data == null)
			return null;
		try {
			DESKeySpec dks = new DESKeySpec(key.subString(0,8).getBytes());
			SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
			// key的长度不能够小于8位字节
			Key secretKey = keyFactory.generateSecret(dks);
			Cipher cipher = Cipher.getInstance(ALGORITHM_DES);
			IvParameterSpec iv = new IvParameterSpec(IV);
			AlgorithmParameterSpec paramSpec = iv;
			cipher.init(Cipher.ENCRYPT_MODE, secretKey, paramSpec);
			byte[] bytes = cipher.doFinal(data.getBytes());
			byte[] str=Base64.encode(bytes,0, bytes.length, 0);
			return new String(str,"UTF-8");
		} catch (Exception e) {
			e.printStackTrace();
			return data;
		}
	}

	/**
	 * DES算法,解密
	 * 
	 * @param data
	 *            待解密字符串
	 * @param key
	 *            解密私钥,长度不能够小于8位
	 * @return 解密后的字节数组
	 * @throws Exception
	 *             异常
	 */
	public static String decode(String key, String data) {
		if (data == null)
			return null;
		try {
			DESKeySpec dks = new DESKeySpec(key.getBytes());
			SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
			// key的长度不能够小于8位字节
			Key secretKey = keyFactory.generateSecret(dks);
			Cipher cipher = Cipher.getInstance(ALGORITHM_DES);
			IvParameterSpec iv = new IvParameterSpec("12345678".getBytes());
			AlgorithmParameterSpec paramSpec = iv;
			cipher.init(Cipher.DECRYPT_MODE, secretKey, paramSpec);
			return new String(cipher.doFinal(byte2hex(data.getBytes())));
		} catch (Exception e) {
			e.printStackTrace();
			return data;
		}
	}

 
 
我对他的代码进行了一些小的修改,首先就是加密方法的红色部分,我们来看一下都是什么东东:

要想知道第一行和第二行的意义,首先我们要先了解

调用DES加密算法包最精要的就是下面两句话:(来自摘抄:http://blog.csdn.net/randyjiawenjie/article/details/6617225,http://jingyan.baidu.com/article/f96699bbb1b3d6894f3c1b66.html)

Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");

   cipher.init(Cipher.ENCRYPT_MODE, key, zeroIv);

  •     Cipher类为加密和解密提供密码功能,转换始终包括加密算法的名称(例如,DES),后面可能跟有一个加密模式和填充方案。Cipher.getInstance的参数格式:"加密算法/加密         模式/填充模式" 或  "算法"
  •     其中的参数含义为:DES为加密算法,CBC为加密模式,PKCS5Padding为填充模式.

  •     常用加密算法:DES、3DES、RC4、AES

  •     加密模式:ECB、CBC、CFB、OFB等;

  • DES一共有电子密码本模式(ECB)、加密分组链接模式(CBC)、加密反馈模式(CFB)和输出反馈模式(OFB)四种模式
  •     填充模式:NoPadding、PKCS1Padding、PKCS5Padding、PKCS7Padding

  •     所以有

  •     

    DES/CBC/PKCS5Padding,
  •     DES/CFB/PKCS5Padding,
  •     DES/ECB/PKCS5Padding,
  •     DES/OFB/PKCS5Padding,
  •     DES/CFB/NoPadding,
  •     DES/CBC/NoPadding,   
  •     DES/ECB/NoPadding,
  •     DES/OFB/NoPadding,
  •     ........
  •     我不会告诉你我是一个一个试出来哪一个能匹配上的。。。。。。
  •     
      cipher.init()一共有三个参数:Cipher.ENCRYPT_MODE, key, zeroIv,zeroIv就是初始化向量,一个8位字符数组(也就是第二行标红的那个)。
  •   工作模式、填充模式、初始化向量这三种因素一个都不能少。否则,如果你不指定的话,那么就要程序就要调用默认实现。问题就来了,这就与平台有关了。
  •   剩下代码中标红的就是将加密结果进行Base64编码,然后将字节数组转换为字符串返回
  •   ================================================================================================
  •   接下来就是C#服务器端了,先看一下DES加密解密代码
  •   <span style="color:#ff0000;">private static byte[] Keys = { 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF };</span>
         /** <summary>
         /// DES加密字符串
          /// </summary>
          /// <param name="encryptString">待加密的字符串</param>
         /// <param name="encryptKey">加密密钥,要求为8位</param>
         /// <returns>加密成功返回加密后的字符串,失败返回源串</returns>
         public static string EncryptDES(string encryptString, string encryptKey)
          {
             try
             {           
                 <span style="color:#ff0000;">byte[] rgbKey = Encoding.UTF8.GetBytes(encryptKey.Substring(0, 8));</span>
                 byte[] rgbIV = Keys;
                 byte[] inputByteArray = Encoding.UTF8.GetBytes(encryptString);
                 DESCryptoServiceProvider dCSP = new DESCryptoServiceProvider();
                 MemoryStream mStream = new MemoryStream();
                 CryptoStream cStream = new CryptoStream(mStream, dCSP.CreateEncryptor(rgbKey, rgbIV), CryptoStreamMode.Write);
                 cStream.Write(inputByteArray, 0, inputByteArray.Length);
                 cStream.FlushFinalBlock();
                 return Convert.ToBase64String(mStream.ToArray());
               }
             catch
             {
                 return encryptString;
             }
         }
    
         /** <summary>
         /// DES解密字符串
         /// </summary>
         /// <param name="decryptString">待解密的字符串</param>
        /// <param name="decryptKey">解密密钥,要求为8位,和加密密钥相同</param>
         /// <returns>解密成功返回解密后的字符串,失败返源串</returns>
         public static string DecryptDES(string decryptString, string decryptKey)
         {
            try
             {
                 byte[] rgbKey = Encoding.UTF8.GetBytes(decryptKey);
                 byte[] rgbIV = Keys;
                 byte[] inputByteArray = Convert.FromBase64String(decryptString);
                 DESCryptoServiceProvider DCSP = new DESCryptoServiceProvider();
                 MemoryStream mStream = new MemoryStream();
                 CryptoStream cStream = new CryptoStream(mStream, DCSP.CreateDecryptor(rgbKey, rgbIV), CryptoStreamMode.Write);
                 cStream.Write(inputByteArray, 0, inputByteArray.Length);
                 cStream.FlushFinalBlock();
                 return Encoding.UTF8.GetString(mStream.ToArray());
              }
             catch
              {
                 return decryptString;
              }
         }
      这里唯一要注意的就是保证   private static byte[] Keys = { 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF } 和Android端的 private static byte[] IV={0x12,0x34,0x56,0x78,(byte) 0x90,         (byte) 0xAB,(byte) 0xCD,(byte) 0xEF} 保持一致,以及是否对加密内容进行了字符串截取,当然最重要的是保证密匙相同。

  •   传说:
  •      a. 有些 明文加密后返回值为null,原来是明文的长度 必须为8的倍数 。增加一个while循环填充空格就可以了。当你处理其他系统间的加密数据交互时,也可以参考一下。
  •             b.  Android平台和Java平台的DES加密解密如果不这样处理也会出现加密解密结果不同的情况。
  •             c. 谁能告诉我为啥在android中(Eclipse) private static byte[] IV={0x12,0x34,0x56,0x78,(byte) 0x90,(byte) 0xAB,(byte) 0xCD,(byte) 0xEF}里后面的数据要进行类型转换


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值