当前位置:首页 > Android

【Android工具类】如何保证Android与服务器的DES加密保持一致

jsc10年前 (2016-09-19)Android3773

    在我们的应用程序涉及到比较敏感的数据的时候,我们通常会对数据进行简单的加密。在与服务器之间的数据交互中,除了可以使用post请求来增强数据的安全性之外,我们可以使用常见的加密算法,对数据进行加密。今天主要介绍的是DES加密算法。

    首先,DES属于一种对称的加密算法,所谓对称,就是说加密和解密使用的都是同一个密钥,那么在我们实际应用的时候,就是指服务器和客户端进行加密解密的时候,使用的是一个相同的密钥。除此之外,还有非对称加密算法,就是公钥私钥机制,这种方式可以被用来进行身份验证,这个以后再细说。    


    DES全称为Data EncryptionStandard,即数据加密标准,是一种使用密钥加密的块算法,DES算法的入口参数有三个:Key、Data、Mode。其中Key为7个字节共56位,是DES算法的工作密钥;Data为8个字节64位,是要被加密或被解密的数据;Mode为DES的工作方式,有两种:加密或解密。

    下面是在Java或者是Android里面,进行DES加密的代码实现

package com.qust.rollcallstudent.utils;  
  
import java.security.InvalidAlgorithmParameterException;  
import java.security.Key;  
import java.security.spec.AlgorithmParameterSpec;  
import java.util.Locale;  
  
import javax.crypto.Cipher;  
import javax.crypto.SecretKeyFactory;  
import javax.crypto.spec.DESKeySpec;  
import javax.crypto.spec.IvParameterSpec;  
  
/** 
 *  
 * @ClassName: com.qust.rollcallstudent.utils.DESUtil 
 * @Description: DES加密解密工具包 
 * @author zhaokaiqiang 
 * @date 2014-11-13 下午8:40:56 
 *  
 */  
public class DESUtil {  
  
    public static final String ALGORITHM_DES = "DES/CBC/PKCS5Padding";  
  
    /** 
     * 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.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.ENCRYPT_MODE, secretKey, paramSpec);  
            byte[] bytes = cipher.doFinal(data.getBytes());  
            return byte2String(bytes);  
        } 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;  
        }  
    }  
  
    /** 
     * 二行制转字符串 
     *  
     * @param b 
     * @return 
     */  
    private static String byte2String(byte[] b) {  
        StringBuilder hs = new StringBuilder();  
        String stmp;  
        for (int n = 0; b != null && n < b.length; n++) {  
            stmp = Integer.toHexString(b[n] & 0XFF);  
            if (stmp.length() == 1)  
                hs.append('0');  
            hs.append(stmp);  
        }  
        return hs.toString().toUpperCase(Locale.CHINA);  
    }  
  
    /** 
     * 二进制转化成16进制 
     *  
     * @param b 
     * @return 
     */  
    private static byte[] byte2hex(byte[] b) {  
        if ((b.length % 2) != 0)  
            throw new IllegalArgumentException();  
        byte[] b2 = new byte[b.length / 2];  
        for (int n = 0; n < b.length; n += 2) {  
            String item = new String(b, n, 2);  
            b2[n / 2] = (byte) Integer.parseInt(item, 16);  
        }  
        return b2;  
    }  
  
}

 如果大家只是想用,就可以不用往下看了,下面开始说一些关于DES算法的细节。


    在上面的加密和解密的方法里面,我们在获取Cipher实例的时候,传入了一个字符串"DES/CBC/PKCS5Padding",这三个参数是什么意思呢?

    实际上,这三个参数分别对应的是“算法/模式/填充”,也就是说我们要用DES算法进行加密,采用的是CBC模式,填充方式采用PKCS5Padding。

    除了CBC模式,还有ECB模式等,指的是不同的加密方式。

    那么CBC模式和ECB模式又有什么区别呢?


    ECB模式指的是电子密码本模式,是一种最古老,最简单的模式,将加密的数据分成若干组,每组的大小跟加密密钥长度相同;然后每组都用相同的密钥加密, 比如DES算法, 如果最后一个分组长度不够64位,要补齐64位。这种模式的特点是:


    1.每次Key、明文、密文的长度都必须是64位;

    2.数据块重复排序不需要检测;

    3.相同的明文块(使用相同的密钥)产生相同的密文块,容易遭受字典攻击;

    4.一个错误仅仅会对一个密文块产生影响;

    

CBC模式指的是加密块链模式,与ECB模式最大的不同是加入了初始向量。下面的代码就是获取一个初始向量,


    IvParameterSpec iv = new IvParameterSpec("12345678".getBytes());

    这种模式的特点是:


    1.每次加密的密文长度为64位(8个字节);

    2.当相同的明文使用相同的密钥和初始向量的时候CBC模式总是产生相同的密文;

    3.密文块要依赖以前的操作结果,所以,密文块不能进行重新排列;

    4.可以使用不同的初始化向量来避免相同的明文产生相同的密文,一定程度上抵抗字典攻击;

    5.一个错误发生以后,当前和以后的密文都会被影响;

    

    PKCS5Padding参数则是在说明当数据位数不足的时候要采用的数据补齐方式,也可以叫做数据填充方式。

    PKCS5Padding这种填充方式,具体来说就是“填充的数字代表所填字节的总数”

    比如说,差两个字节,就是######22,差5个字节就是###55555,这样根据最后一个自己就可以知道填充的数字和数量。

   

    介绍完DES的这些细节之后,我们就可以知道,在不同的平台上,只要能保证这几个参数的一致,就可以实现加密和解密的一致性。

    1.加密和解密的密钥一致

    2.采用CBC模式的时候,要保证初始向量一致

    3.采用相同的填充模式

转载请注明出处:http://blog.csdn.net/zhaokaiqiang1992

扫描二维码推送至手机访问。

版权声明:本文由微小站发布,如需转载请注明出处。

本文链接:https://jsc0.com/post/118.html

标签: dex数据加密
分享给朋友:

“【Android工具类】如何保证Android与服务器的DES加密保持一致” 的相关文章

Fragment保持状态切换

Fragment保持状态切换

在使用Activity管理多个Fragment时,每次切换Fragment使用的是replace,结果导致出现xxx is not currently in the FragmentManager异常挂掉网上说使用replace切换会使被切换的Fragment给替换掉,从而被被切换的Fra…

制作一款Android APK管理器主要代码

Android APK管理器代码,主要就是两个列表,一个显示SD卡上面的APK文件的list,一个显示已经安装的app的list。1:获取SD卡上的APK安装文件后,要用代码读出APK里面的信息,如icon等,的主要代码如下:private void getUninatllApk…

获取Android手机中SD卡存储信息

SD卡作为手机的扩展存储设备,在手机中充当硬盘角色,可以让我们手机存放更多的数据以及多媒体等大体积文件。因此查看SD卡的内存就跟我们查看硬盘的剩余空间一样,是我们经常操作的一件事,那么在Android开发中,我们如何能获取SD˂span style="font-family:宋…

Sipnner点击相同Item不响应的解决方法

Spinner,两次点击同一个item的时候,第二次会不响应OnItemSelect事件。解决方法:@Override public void onItemSelected(AdapterView<?> arg0, View arg1,…

Location服务之LocationManager

Location服务之LocationManager

LocationManager系统服务是位置服务的核心组件,它提供了一系列方法来处理与位置相关的问题,包括查询上一个已知位置、注册和注销来 自某个LocationProvider的周期性的位置更新、注册和注销接近某个坐标时对一个已定义的Intent的触发等。今天我们就一起探讨一下 Locatio…

Android学习笔记--用户定位User Location

Android学习笔记--用户定位User Location

用户定位 User Location的作用: 1.获取用户的位置 2.追踪用户的移动 User Location的关键API…