Android使用AES加密时遇到的问题及解决办法

什么是AES加密,可查看博客 :https://blog.csdn.net/chenhuakang/article/details/80223202?utm_medium=distribute.pc_relevant.none-task-blog-baidujs_title-0&spm=1001.2101.3001.4242

需要注意的点有如下:

1、算法的名称与加密时是否相同

2、加密和解密时的模式、填充是否相同

3、加密和解密时的密钥是否相同

4、模式、填充是否是该算法支持的

会出现的问题有

1、InvalidAlgorithmParameterException异常expected IV length of 16 but was 8

解决办法:

/**
* 补码
* aes加密的向量为16位,des加密的向量为8位,当不足时需要补位,否则抛异常。
* 补码 这里不能补"0",要补 "\0",因为在ASCII码中"0"48,所以需要把0转译,故"\0"才为0
*
* @param iv
* @return
*/
private static byte[] getIv(String iv) {
StringBuffer buffer = new StringBuffer(16);
buffer.append(iv);
while (buffer.length() < 16) {
buffer.append("\0");
}
if (buffer.length() > 16) {
buffer.setLength(16);
}
return buffer.toString().getBytes();
}

2、javax.crypto.BadPaddingException: error:1e000065:Cipher functions:OPENSSL_internal:BAD_DECRYPT

导致这个问题的原因就是 密钥不对 ,要严格按照密钥的生成规则
解决办法可参考如下:
private static final String ALGORITHM = "AES/CBC/PKCS5Padding";
private static final String ENCODING = "utf-8";
private static final String ALGORITHM_AES = "AES";
private static final String KEY = "换成你自己的key"; //密钥 key跟后台协商一个即可,保持一致
private static final String IV = "换成你自己的iv"; // 密钥向量,这里的偏移量也需要跟后台一致,一般跟key一样就行

/**
 * 加密
 *
 * @param srcData 原数据
 * @return
 * @throws Exception
 */
public static String encryptAESCBC(String srcData) throws Exception {
    SecretKeySpec keySpec = new SecretKeySpec(KEY.getBytes(), ALGORITHM_AES);
    Cipher cipher = Cipher.getInstance(ALGORITHM);
    //使用CBC模式必须指定IvParameterSpec,且expected IV length of 16,即长度限制为16
    //如果报异常,IV.getBytes()换成第一点中的getIv(IV)方法即可
    cipher.init(Cipher.ENCRYPT_MODE, keySpec, new IvParameterSpec(IV.getBytes()));
    byte[] encData = cipher.doFinal(srcData.getBytes(ENCODING));
    return parseByte2HexStr(encData);
}

/**
 * 解密
 *
 * @param encData 需解密数据
 * @return
 * @throws Exception
 */
public static String decryptAESCBC(String encData) throws Exception {
    SecretKeySpec keySpec = new SecretKeySpec(KEY.getBytes(), ALGORITHM_AES);
    Cipher cipher = Cipher.getInstance(ALGORITHM);
    cipher.init(Cipher.DECRYPT_MODE, keySpec, new IvParameterSpec(IV.getBytes()));
    byte[] decryptData = cipher.doFinal(parseHexStr2Byte(encData));
    return new String(decryptData, ENCODING);
}

/**
 * 将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;
}

/**
 * 将二进制转换成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();
}

3、javax.crypto.IllegalBlockSizeException: error:1e00007b:Cipher functions:OPENSSL_internal:WRONG_FINAL_BLOCK_LENGTH 报这个问题的解决办法可参考 https://www.cnblogs.com/lsdb/p/9324372.html

4、加解密参考代码:

/**
* 加密
*
* @param srcData 原数据
* @param key 密钥
* @param iv 密钥向量
* @return
* @throws Exception
*/
public static byte[] encryptAESCBC(byte[] srcData, byte[] key, byte[] iv) throws Exception {
SecretKeySpec keySpec = new SecretKeySpec(key, ALGORITHM_AES);
Cipher cipher = Cipher.getInstance(ALGORITHM);
cipher.init(Cipher.ENCRYPT_MODE, keySpec, new IvParameterSpec(iv));
byte[] encData = cipher.doFinal(srcData);
return encData;
}

/**
* 解密
*
* @param encData 需解密数据
* @param key 密钥
* @param iv 密钥向量
* @return
* @throws Exception
*/
public static String decryptAESCBC(byte[] encData, byte[] key, byte[] iv) throws Exception {
SecretKeySpec keySpec = new SecretKeySpec(key, ALGORITHM_AES);
Cipher cipher = Cipher.getInstance(ALGORITHM);
cipher.init(Cipher.DECRYPT_MODE, keySpec, new IvParameterSpec(iv));
return new String(cipher.doFinal(encData), Charset.forName(ENCODING));

}

发生错误时,先确认是否满足了需要注意的点。

Android 集成FaceBook登录所遇到的问题

Facebook官方集成的文档地址:https://developers.facebook.com/docs/facebook-login/android/

1、生成发布密钥散列需要注意事项:

需要先安装openssl,否则会报’openssl’ 不是内部或外部命令,也不是可运行的程序 或批处理文件。

安装教程可参考 https://blog.csdn.net/sunhuansheng/article/details/82218678?

2、密钥散列可添加多个,如图所示

3、应用程序不设置:此应用程序仍处于开发模式,您无权访问它。切换到注册的测试用户或请求应用管理员获取权限或者报ERVER_ERROR: [code] 1675030 [message]: 执行查询时出错。 [extra]:,只需要在手机内部的facebook app上登录以下所设置的账号即可,如图