自学Android开发 AES加密

追求适度,才能走向成功;人在顶峰,迈步就是下坡;身在低谷,抬足既是登高;弦,绷得太紧会断;人,思虑过度会疯;水至清无鱼,人至真无友,山至高无树;适度,不是中庸,而是一种明智的生活态度。

导读:本篇文章讲解 自学Android开发 AES加密,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com,来源:原文

一、问题

在Java 后端发来的AES加密数据时,发现Android APP不能解密 而且Android 端 加密同样的数据返回的结果居然不一致,所以我在网上查询后,发现在SecureRandom在产生安全随机数时 Windows系统和Linux系统的机制不一样,所以在同样的java AES加密源码加密同意的数据产生不一样的加密结果。

下面我给出网络的常用的AES加密的源码。

网络常用的AES加解密源码:

/**
     * AES加密字符串
     *
     * @param content
     *            需要被加密的字符串
     * @param password
     *            加密需要的密码
     * @return 密文
     */
    public static byte[] encrypt(String content, String password) {
        try {
            KeyGenerator kgen = KeyGenerator.getInstance("AES");// 创建AES的Key生产者

            kgen.init(128, new SecureRandom(password.getBytes()));// 利用用户密码作为随机数初始化出
                                                                    // 128位的key生产者
            //加密没关系,SecureRandom是生成安全随机数序列,password.getBytes()是种子,只要种子相同,序列就一样,所以解密只要有password就行

            SecretKey secretKey = kgen.generateKey();// 根据用户密码,生成一个密钥

            byte[] enCodeFormat = secretKey.getEncoded();// 返回基本编码格式的密钥,如果此密钥不支持编码,则返回
                                                            // null。

            SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");// 转换为AES专用密钥

            Cipher cipher = Cipher.getInstance("AES");// 创建密码器

            byte[] byteContent = content.getBytes("utf-8");

            cipher.init(Cipher.ENCRYPT_MODE, key);// 初始化为加密模式的密码器

            byte[] result = cipher.doFinal(byteContent);// 加密

            return result;

        } catch (NoSuchPaddingException e) {
            e.printStackTrace();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        } catch (IllegalBlockSizeException e) {
            e.printStackTrace();
        } catch (BadPaddingException e) {
            e.printStackTrace();
        }
        return null;
    }


/**
     * 解密AES加密过的字符串
     *
     * @param content
     *            AES加密过过的内容
     * @param password
     *            加密时的密码
     * @return 明文
     */
    public static byte[] decrypt(byte[] content, String password) {
        try {
            KeyGenerator kgen = KeyGenerator.getInstance("AES");// 创建AES的Key生产者
            kgen.init(128, new SecureRandom(password.getBytes()));
            SecretKey secretKey = kgen.generateKey();// 根据用户密码,生成一个密钥
            byte[] enCodeFormat = secretKey.getEncoded();// 返回基本编码格式的密钥
            SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");// 转换为AES专用密钥
            Cipher cipher = Cipher.getInstance("AES");// 创建密码器
            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;
    }

二、解决源码

我的解决方案是自己写AES的秘钥生成128位的Key和使用Java Base64加密生成加密数据字符串;这样可以避免因为系统的随机数机制不同而不能加解密。

我的AES源码:


import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;

/**
 * AES加密工具
 * <p>
 * 加密流程 AES -> BAse64
 * 解密流程 Base64 -> AES
 */
public class AESUtil {
    //补充字典
    private final static String DIC = "1231g81f5456hhssg84h1f9q3f2x789s";

    // 加密
    public static String encrypt(String str, String key) {
        if (str == null || "".equals(str))
            return null;
        if (key == null || "".equals(key))
            return null;
        try {
            byte[] enCodeFormat = generateKey(key);// 返回基本编码格式的密钥,如果此密钥不支持编码,则返回
            SecretKeySpec skey = new SecretKeySpec(enCodeFormat, "AES");// 转换为AES专用密钥
            Cipher cipher = Cipher.getInstance("AES");// 创建密码器
            cipher.init(Cipher.ENCRYPT_MODE, skey);// 初始化为加密模式的密码器
            byte[] result = cipher.doFinal(str.getBytes("UTF-8"));// 加密
            return Base64.getUrlEncoder().encodeToString(result);
        } catch (Exception e) {
            LogUtil.e(e.toString());
            return null;
        }
    }

    // 解密
    public static String decrypt(String str, String key) {
        if (str == null || "".equals(str))
            return null;
        if (key == null || "".equals(key))
            return null;
        try {
            byte[] enCodeFormat = generateKey(key);// 返回基本编码格式的密钥
            SecretKeySpec skey = new SecretKeySpec(enCodeFormat, "AES");// 转换为AES专用密钥
            Cipher cipher = Cipher.getInstance("AES");// 创建密码器
            cipher.init(Cipher.DECRYPT_MODE, skey);// 初始化为解密模式的密码器
            byte[] base64 = Base64.getUrlDecoder().decode(str.getBytes("UTF-8"));
            byte[] result = cipher.doFinal(base64);
            return new String(result, "UTF-8"); // 明文
        } catch (Exception e) {
            LogUtil.e(e.getMessage());
            return null;
        }
    }

    /**
     * 自定义 秘钥补充
     *
     * @param key
     * @return
     * @throws Exception
     */
    private static byte[] generateKey(String key) throws Exception {
        byte[] dics = DIC.getBytes("UTF-8");
        byte[] bkeys = key.getBytes("UTF-8");
        byte[] keys = bkeys;
        int keylength = bkeys.length;
        if (keylength > 0 && keylength < 16) {
            keys = new byte[16];
            System.arraycopy(bkeys, 0, keys, 0, keylength);
            for (int i = keylength; i < 16; i++) {
                keys[i] = dics[i];
            }
        }

        if (keylength > 16 && keylength < 24) {
            keys = new byte[24];
            System.arraycopy(bkeys, 0, keys, 0, keylength);
            for (int i = keylength; i < 24; i++) {
                keys[i] = dics[i];
            }
        }

        if (keylength > 24 && keylength < 32) {
            keys = new byte[32];
            System.arraycopy(bkeys, 0, keys, 0, keylength);
            for (int i = keylength; i < 32; i++) {
                keys[i] = dics[i];
            }
        }

        if (keylength > 32) {
            keys = new byte[32];
            System.arraycopy(bkeys, 0, keys, 0, 32);
        }

        return keys;
    }

generateKey()的用于生成AES使用的128位秘钥;

注意:DIC这个秘钥补充字典 这个可以自己定义,但是一定要和java 后端一致。

加密解密时使用Base64我有相关的文章可以去参考一下:

自学Android开发 Java和Android SDK的Base64icon-default.png?t=M276https://blog.csdn.net/Ym_quiet/article/details/123835335?spm=1001.2014.3001.5501

如果对您有一些意义,希望您给博主一些鼓励(点赞、关注、收藏),如果有错误欢迎大家评论。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/128356.html

(0)
飞熊的头像飞熊bm

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!