Android 中使用 java AES 加密

1 前言

java开发中,加密还是一个非常常见的需求,常见的加密有对称加密和非对称加密两种,这两种使用的加密解密密钥方式不同。这里暂且不去讨论详细的加密原理。在java中AES加密用的比较多

2 AES对称加密

AES加密是一种对称加密,即加密和解密的密钥是相同的。在Android中,使用AES的加密如下:

/**
 * @author Created by qiyei2015 on 2017/12/13.
 * @version: 1.0
 * @email: 1273482124@qq.com
 * @description:
 */
public class AES {

    private static final String TAG = AES.class.getSimpleName();


    /**
     * 生成SecretKey
     * @param rules 生成规则
     * @return
     */
    private static SecretKeySpec generateSecretKey(String rules){
        try {
            //1.构造密钥生成器,指定为AES算法,不区分大小写
            KeyGenerator keygen = KeyGenerator.getInstance("AES");
            //2.根据规则初始化密钥生成器  生成一个128位的随机源,根据传入的字节数组
            // 注意生成随机数的方式,否则在Android系统中可能会报错
            SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG", new CryptoProvider());
            secureRandom.setSeed(rules.getBytes("utf-8"));
            keygen.init(128,secureRandom);
            //3.产生原始对称密钥
            SecretKey originalKey = keygen.generateKey();
            //4.获得原始对称密钥的字节数组
            byte [] raw = originalKey.getEncoded();
            //5.根据字节数组生成AES密钥
            SecretKeySpec key = new SecretKeySpec(raw, "AES");
            return key;
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * AES加密
     * @param rules 规则
     * @param plainText 明文
     * @return 加密后的密文
     */
    public static byte[] encrypt(String rules,String plainText){
        if (TextUtils.isEmpty(rules)){
            return null;
        }
        if (plainText == null || plainText.length() == 0){
            return null;
        }
        try {
            SecretKeySpec key = generateSecretKey(rules);
            if (key != null){
                //1.根据指定算法AES自成密码器
                Cipher cipher = Cipher.getInstance("AES");
                //2.初始化密码器,第一个参数为加密(Encrypt_mode)或者解密(Decrypt_mode)操作,第二个参数为使用的KEY
                cipher.init(Cipher.ENCRYPT_MODE, key);
                //3. 加密
                byte [] byteEncode = cipher.doFinal(plainText.getBytes("utf-8"));
                return byteEncode;
            }
        } 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();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * AES解密
     * @param rules 规则
     * @param encryptText 密文
     * @return 解密后的明文
     */
    public static byte[] decrypt(String rules,byte[] encryptText){
        if (TextUtils.isEmpty(rules)){
            return null;
        }
        if (encryptText == null || encryptText.length == 0){
            return null;
        }

        try {
            SecretKeySpec key = generateSecretKey(rules);
            if (key != null){
                //6.根据指定算法AES自成密码器
                Cipher cipher = Cipher.getInstance("AES");
                //7.初始化密码器,第一个参数为加密(Encrypt_mode)或者解密(Decrypt_mode)操作,第二个参数为使用的KEY
                cipher.init(Cipher.DECRYPT_MODE, key);
                //8. 解密
                byte [] byteDecode = cipher.doFinal(encryptText);
                return byteDecode;
            }
        } 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;
    }


    /**
     * 将二进制转换成16进制
     * @param buffer 二进制数组
     * @return 十六进制字符串
     */
    public static String parseByte2HexStr(byte buffer[]) {
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < buffer.length; i++) {
            String hex = Integer.toHexString(buffer[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;
    }

}
/**
 * @author Created by qiyei2015 on 2017/12/16.
 * @version: 1.0
 * @email: 1273482124@qq.com
 * @description:
 */
public class CryptoProvider extends Provider {

    public CryptoProvider() {
        super("Crypto", 1.0, "HARMONY (SHA1 digest; SecureRandom; SHA1withDSA signature)");
        put("SecureRandom.SHA1PRNG",
                "org.apache.harmony.security.provider.crypto.SHA1PRNG_SecureRandomImpl");
        put("SecureRandom.SHA1PRNG ImplementedIn", "Software");
    }

}

一般来说,我们都会将加密和解密的接口进行封装,因此封装的接口如下:

/**
 * @author Created by qiyei2015 on 2017/12/13.
 * @version: 1.0
 * @email: 1273482124@qq.com
 * @description: 加密Manager
 */
public class EncryptManager {

    private static final String TAG = AES.class.getSimpleName();

    /**
     * 加密
     * @param rules 加密规则
     * @param plainText 加密前的明文
     * @return 加密后的密文 16进制字符串
     */
    public static String encrypt(String rules,String plainText){
        if (TextUtils.isEmpty(plainText) || TextUtils.isEmpty(rules)){
            return null;
        }
        byte[] encryptResult = AES.encrypt(rules,plainText);
        if (encryptResult != null){
            return AES.parseByte2HexStr(encryptResult);
        }
        return null;
    }

    /**
     * 解密
     * @param rules
     * @param encryptText 加密后的密文 16进制字符串
     * @return 加密前的明文
     */
    public static String decrypt(String rules,String encryptText){
        if (TextUtils.isEmpty(encryptText) || TextUtils.isEmpty(rules)){
            return null;
        }
        byte[] decryptResult = AES.decrypt(rules,AES.parseHexStr2Byte(encryptText));
        if (decryptResult != null){
            try {
                return new String(decryptResult,"utf-8");
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
        }
        return null;
    }

}

另外,在实际开发中需要对加密和解密的规则需要做特殊处理,防止反编译被发现等。如果是固定规则,可以考虑放在so库中,防止反编译。

3 加密示例

下面是一个AES加密和解密的示例:

public class EncryptActivity extends AppCompatActivity {


    private EditText mEditTextRules;

    private EditText mEditTextContent;

    private TextView mTextViewResult;

    private Button mButton1;

    private Button mButton2;

    String encryptResult;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_encrypt);

        mEditTextRules = (EditText) findViewById(R.id.edt1);
        mEditTextContent = (EditText) findViewById(R.id.edt2);

        mTextViewResult = (TextView) findViewById(R.id.tv2);

        mButton1 = (Button) findViewById(R.id.btn1);
        mButton2 = (Button) findViewById(R.id.btn2);

        mButton1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                encryptResult = EncryptManager.encrypt(mEditTextRules.getText().toString(),mEditTextContent.getText().toString());
                mTextViewResult.setText("加密结果:" + encryptResult);
            }
        });

        mButton2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                String result = EncryptManager.decrypt(mEditTextRules.getText().toString(),encryptResult);
                mTextViewResult.setText("加密结果:" + encryptResult
                        + "\n\n" + "解密结果:" + result);
            }
        });

    }
}

程序运行效果如下:
这里写图片描述

源代码参考:
https://github.com/qiyei2015/EssayJoke SDK encrypt部分

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值