Android与Java服务端加密解密

来源:互联网 发布:c语言二维数组例子 编辑:程序博客网 时间:2024/05/19 08:37

本篇博客是使用Android端与Java服务端交互——SocketIO中的通信方式连接Android客户端和java服务器端的。如果对这方面没有了解过的,可以随意去看看;如果对这方面没有需求或者只关心加密操作的同志请继续。

在Android端做数据加密操作以前在做毕业设计的时候就想把这个功能加进去,奈何时间有限,知识有限再加上这个需求并没有那么迫切,时间一长就没有继续纠缠下去了。现如今,项目中要求加上这个功能,没办法,只能硬着头皮上咯。

一通google之后,搜了不少有用的资料作为存档,贴出来也给大人们享受享受。

1.PHP,安卓,ios相互适用的AES加密算法    http://wangsigui.blog.51cto.com/5362901/13404152.iOS,Android,WP, .NET通用AES加密算法    http://www.cnblogs.com/mantgh/p/4244891.html3.Android、iPhone和Java三个平台一致的加密工具    http://www.iteye.com/topic/11279494.关于AES256算法java端加密,ios端解密出现无法解密问题的解决方案    http://my.oschina.net/nicsun/blog/956325.Android与IOS通用AES加密解密方法    http://blog.csdn.net/yuxikuo_1/article/details/394760716.android、ios与服务器端php使用rsa加密解密通讯    http://blog.csdn.net/xyxjn/article/details/172258097.PHP android ios相互兼容的AES加密算法    http://www.funboxpower.com/868.html8.Android DES AES MD5加密    http://m.blog.csdn.net/blog/u014071669/393416899.Java Base64、AES、SHA1、MD5加密算法    http://my.oschina.net/u/1447924/blog/37779810.在Java、Android、PHP實現AES加解密,並且互通的方式    http://magiclen.org/aes/11.AES Encryption : AES « Security « Android    http://www.java2s.com/Code/Android/Security/AESEncryption.htm12.Given final block not properly padded    http://bbs.csdn.net/topics/8006475113.android 和java平台通用的AES加密解密(Android端与java端互相解密的解决方案)    http://my.oschina.net/wangxnn/blog/390346

好了,以上就是我所搜集的有关AES加密相关的资料了,因为在网上搜了一通发现目前AES加密这一块安全性能还不错,大部分人都推荐使用,so,跟着人民群众走不会错的,当然,如果你有更好的加密操作的话,可以分享给我,在此小生先谢谢各位了。

进入正题吧,先贴出代码:

package com.netty.server.util;import java.io.UnsupportedEncodingException;import java.security.InvalidKeyException;import java.security.Key;import java.security.NoSuchAlgorithmException;import javax.crypto.BadPaddingException;import javax.crypto.Cipher;import javax.crypto.IllegalBlockSizeException;import javax.crypto.KeyGenerator;import javax.crypto.NoSuchPaddingException;import javax.crypto.spec.SecretKeySpec;public class AESUtils {    static final String algorithmStr = "AES/ECB/PKCS5Padding";    private static final Object TAG = "AES";    static private KeyGenerator keyGen;    static private Cipher cipher;    static boolean isInited = false;      private static  void init() {        try {                 /**为指定算法生成一个 KeyGenerator 对象。                *此类提供(对称)密钥生成器的功能。                *密钥生成器是使用此类的某个 getInstance 类方法构造的。                *KeyGenerator 对象可重复使用,也就是说,在生成密钥后,                *可以重复使用同一 KeyGenerator 对象来生成进一步的密钥。                *生成密钥的方式有两种:与算法无关的方式,以及特定于算法的方式。                *两者之间的惟一不同是对象的初始化:                *与算法无关的初始化                *所有密钥生成器都具有密钥长度 和随机源 的概念。                *此 KeyGenerator 类中有一个 init 方法,它可采用这两个通用概念的参数。                *还有一个只带 keysize 参数的 init 方法,                *它使用具有最高优先级的提供程序的 SecureRandom 实现作为随机源                *(如果安装的提供程序都不提供 SecureRandom 实现,则使用系统提供的随机源)。                *此 KeyGenerator 类还提供一个只带随机源参数的 inti 方法。                *因为调用上述与算法无关的 init 方法时未指定其他参数,                *所以由提供程序决定如何处理将与每个密钥相关的特定于算法的参数(如果有)。                *特定于算法的初始化                *在已经存在特定于算法的参数集的情况下,                *有两个具有 AlgorithmParameterSpec 参数的 init 方法。                *其中一个方法还有一个 SecureRandom 参数,                *而另一个方法将已安装的高优先级提供程序的 SecureRandom 实现用作随机源                *(或者作为系统提供的随机源,如果安装的提供程序都不提供 SecureRandom 实现)。                *如果客户端没有显式地初始化 KeyGenerator(通过调用 init 方法),                *每个提供程序必须提供(和记录)默认初始化。                */            keyGen = KeyGenerator.getInstance("AES");        } catch (NoSuchAlgorithmException e) {            e.printStackTrace();        }        // 初始化此密钥生成器,使其具有确定的密钥长度。        keyGen.init(256); //256位的AES加密        try {                    // 生成一个实现指定转换的 Cipher 对象。            cipher = Cipher.getInstance(algorithmStr);        } catch (NoSuchAlgorithmException e) {            e.printStackTrace();        } catch (NoSuchPaddingException e) {            e.printStackTrace();        }        //标识已经初始化过了的字段        isInited = true;    }    private static byte[] genKey() {        if (!isInited) {            init();          }        //首先 生成一个密钥(SecretKey),        //然后,通过这个秘钥,返回基本编码格式的密钥,如果此密钥不支持编码,则返回 null。         return keyGen.generateKey().getEncoded();    }    private static byte[] encrypt(byte[] content, byte[] keyBytes) {        byte[] encryptedText = null;        if (!isInited) {             init();        }        /**        *类 SecretKeySpec        *可以使用此类来根据一个字节数组构造一个 SecretKey,        *而无须通过一个(基于 provider 的)SecretKeyFactory。        *此类仅对能表示为一个字节数组并且没有任何与之相关联的钥参数的原始密钥有用         *构造方法根据给定的字节数组构造一个密钥。        *此构造方法不检查给定的字节数组是否指定了一个算法的密钥。        */        Key key = new SecretKeySpec(keyBytes, "AES");        try {                // 用密钥初始化此 cipher。            cipher.init(Cipher.ENCRYPT_MODE, key);        } catch (InvalidKeyException e) {            e.printStackTrace();        }        try {                //按单部分操作加密或解密数据,或者结束一个多部分操作。(不知道神马意思)            encryptedText = cipher.doFinal(content);        } catch (IllegalBlockSizeException e) {            e.printStackTrace();        } catch (BadPaddingException e) {            e.printStackTrace();        }        return encryptedText;    }    private static byte[] encrypt(String content, String password) {        try {            byte[] keyStr = getKey(password);            SecretKeySpec key = new SecretKeySpec(keyStr, "AES");            Cipher cipher = Cipher.getInstance(algorithmStr);//algorithmStr                      byte[] byteContent = content.getBytes("utf-8");            cipher.init(Cipher.ENCRYPT_MODE, key);//   ʼ              byte[] result = cipher.doFinal(byteContent);            return result; //             } catch (NoSuchAlgorithmException e) {            e.printStackTrace();        } catch (NoSuchPaddingException e) {            e.printStackTrace();        } catch (InvalidKeyException e) {            e.printStackTrace();        } catch (UnsupportedEncodingException e) {            e.printStackTrace();        } catch (IllegalBlockSizeException e) {            e.printStackTrace();        } catch (BadPaddingException e) {            e.printStackTrace();        }        return null;    }    private static byte[] decrypt(byte[] content, String password) {        try {            byte[] keyStr = getKey(password);            SecretKeySpec key = new SecretKeySpec(keyStr, "AES");            Cipher cipher = Cipher.getInstance(algorithmStr);//algorithmStr                       cipher.init(Cipher.DECRYPT_MODE, key);//   ʼ              byte[] result = cipher.doFinal(content);            return result; //             } catch (NoSuchAlgorithmException e) {            e.printStackTrace();        } catch (NoSuchPaddingException e) {            e.printStackTrace();        } catch (InvalidKeyException e) {            e.printStackTrace();        } catch (IllegalBlockSizeException e) {            e.printStackTrace();        } catch (BadPaddingException e) {            e.printStackTrace();        }        return null;    }    private static byte[] getKey(String password) {        byte[] rByte = null;        if (password!=null) {            rByte = password.getBytes();        }else{            rByte = new byte[24];        }        return rByte;    }    /**     * 将二进制转换成16进制     * @param buf     * @return     */    public static String parseByte2HexStr(byte buf[]) {        StringBuffer sb = new StringBuffer();        for (int i = 0; i < buf.length; i++) {            String hex = Integer.toHexString(buf[i] & 0xFF);            if (hex.length() == 1) {                hex = '0' + hex;            }            sb.append(hex.toUpperCase());        }        return sb.toString();    }    /**     * 将16进制转换为二进制     * @param hexStr     * @return     */    public static byte[] parseHexStr2Byte(String hexStr) {        if (hexStr.length() < 1)            return null;         byte[] result = new byte[hexStr.length() / 2];        for (int i = 0; i < hexStr.length() / 2; i++) {            int high = Integer.parseInt(hexStr.substring(i * 2, i * 2 + 1), 16);            int low = Integer.parseInt(hexStr.substring(i * 2 + 1, i * 2 + 2),                    16);            result[i] = (byte) (high * 16 + low);        }        return result;    }        //注意: 这里的password(秘钥必须是16位的)    private static final String keyBytes = "abcdefgabcdefg12";     /**    *加密    */    public static String encode(String content){            //加密之后的字节数组,转成16进制的字符串形式输出        return parseByte2HexStr(encrypt(content, keyBytes));    }    /**    *解密    */    public static String decode(String content){            //解密之前,先将输入的字符串按照16进制转成二进制的字节数组,作为待解密的内容输入        byte[] b = decrypt(parseHexStr2Byte(content), keyBytes);        return new String(b);    }}

对这一段代码的了解并不是很透彻,代码也是参照着android 和java平台通用的AES加密解密完成的,在此感谢一下这位博主的经验分享。

哦,需要注意的一点是中间有一段代码keyGen.init(256);这里可能会出现异常Illegal key size or default parameters,各位请不要惊慌,这里写图片描述。解决方案请参照这篇博客中的方法AES加密时抛出java.security.InvalidKeyException: Illegal key size or default parameters。
我在这里也简单的总结一下步骤供大人们使用咯:

去orcale官网搜索jce + " " + jdk版本,例如jce 6,找到相关的下载链接,下载后解压选择解压后文件夹中的local_policy.jar和US_export_policy.jar替换掉你的jdk安装目录下的/jre/lib/security/目录下的两个同名文件即可解决上述异常。

好了,本次的内容到此结束了,希望对您有点收获。

源码由于和上次的几乎一样,只是加了一个加密工具类文件,在数据传输的时候加了调用了加密工具类中的加密解密方法,贴上SocketIO通讯的源码,有需要的可以载下来,自己加上加密解密操作。

传送门

0 0
原创粉丝点击