美文网首页
Java实现AES数据加密

Java实现AES数据加密

作者: 满天星爱我 | 来源:发表于2018-02-28 19:41 被阅读244次
android.png

前言

作为一个Android开发者,通常都要对一些重要的内容进行加密,以免数据被他人窃取,造成不可必要的损失。加密方式有很多种,在这里我只介绍一种,也是Android开发中经常用到的对称加密算法AES。

AES发展史和算法

关于AES的发展和算法详解,大家有兴趣的话可以参阅这篇文章:http://blog.csdn.net/lrwwll/article/details/78069013

什么是AES?

AES是高级加密标准(英语:Advanced Encryption Standard,缩写:AES)。
在密码学中又称Rijndael加密法,是美国联邦政府采用的一种区块加密标准。这个标准用来替代原先的DES,已经被多方分析且广为全世界所使用。

对称加密和非对称加密

  • 对称加密
    所谓的对称加密就是采用单钥密码系统的加密方式,同一个密钥可以同时用作数据的加密与解密,由于其速度快,对称加密通常在消息发送方需要加密大量数据时使用,也被称作单密钥加密,在对称加密算法中,数据发信方将明文(原始数据)和加密密钥一起经过特殊加密算法处理后,使其变成复杂的加密密文发送出去。收信方收到密文后,若想解读原文,则需要使用加密用过的密钥及相同算法的逆算法对密文进行解密,才能使其恢复成可读明文。
  • 非对称加密
    非对称加密在加密的过程中使用一对密钥,而不像对称加密只使用一个单独的密钥。一对密钥中一个用于加密,另一个用来解密。如用A加密,则用B解密;如果用B加密,则要用A解密。

在JAVA中如何使用?

在Java中使用AES进行加解密的逻辑大致如下:

  • 生成/获取密钥
  • 加/解密

下面来看看详细的实现过程:

生成密钥
  • 构建KeyGenerator对象

在Java Api文档的javax.cropto包下专门为开发者提供了一套用于加密操作的类和接口,此包下有一个类KeyGenerator,此类提供了(对称)密钥生成器的功能,并通过静态方法getInstance(...)来获取该对象,代码如下:

KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");

该静态方法中需要传入指定加密算法的名称,当然,还有其他算法。例如:
Blowfish、DES、DESede、HmacMD5或HmacSHA1等,这些算法都可以实现加密。

  • 初始化密钥生成器
       keyGenerator.init(128, new SecureRandom(password.getBytes()));
    

通过查看接口文档,我发现此方法有三个,这里我直接使用参数最多的方法。
首先看第一个参数keysize,看名字就知道此参数指定了密钥的长度(单位:bit),而不同算法的密钥长度是有规定的,AES可以是128,192或256,但是JDK加密库对密钥长度限制在128位以下,所以这里直接传128,传其它则会抛出异常;如果需要在AES中使用128位以上密钥加密时,必须下载扩展的加密库包,下载地址:
http://blog.csdn.net/shangpusp/article/details/7416603

第二个参数要传一个SecureRandom对象,此对象实现了真正意义上的随机,在它的构造方法中可以指定传一个字节数组,这里称为种子,其实就是生成安全随机数序列的初始值,用来生成用户指定的随机数序列,同一个种子,生成的随机数序列是一模一样的。

  • 生成AES专用密钥
    SecretKey secretKey = keyGenerator.generateKey();
    byte[] enCodeFormat = secretKey.getEncoded();
    SecretKeySpec aesKeySpec = new SecretKeySpec(enCodeFormat, "AES");
    

上面的generateKey(...)方法主要用来生成一个新的对称密钥,而下面的 SecretKeySpec则是它的实现类,这里我指定生成了一个AES专用密钥,参数传入此密钥的字节数组格式和密钥的名称(名字自己定),下面是密钥生成的完整代码:

 /**
 *
 * 生成AES密钥
 * @param password 指定随机源的种子
 * @return
 */
public static SecretKeySpec createKey(String password) {
    try {
        //指定加密算法的名称为AES,
        KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
        //初始化密钥生成器,指定密钥的长度(单位:bit),
        //SecureRandom是生成安全随机数序列
        SecureRandom secureRandom =  new SecureRandom(password.getBytes());
        keyGenerator.init(128, secureRandom);
        //生成原始对称密钥
        SecretKey secretKey = keyGenerator.generateKey();
        //返回编码格式的密钥
        byte[] enCodeFormat = secretKey.getEncoded();
        //根据字节数组生成AES专用密钥
        SecretKeySpec aesKeySpec = new SecretKeySpec(enCodeFormat, "AES");
        //返回AES密钥
        return aesKeySpec;

    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    }
    return null;
}
加/解密
  • 加密
  /**
 * 明文加密
 *
 * @param key AES密钥
 * @param content  加密前的原内容
 * @return 
 */ 
public static String encrypt(SecretKeySpec key, String content) {
    try {

        //根据指定算法生成密码器
        Cipher ciper = Cipher.getInstance("AES");
        //初始化密码器,
        // 第一个参数为密码的操作模式:加密(ENCRYPT_MODE),解密(DECRYPT_MODE)
        //第二个参数为AES密钥
        ciper.init(Cipher.ENCRYPT_MODE,key);
        //获取加密内容的字节数组
        byte[] contentBytes = content.getBytes("utf-8");
        byte[] aesBytes = ciper.doFinal(contentBytes);
        //为了避免解密时数据丢失,将加密后的内容进行Base64编码后再返回
        String aesContent = Base64.encodeToString(aesBytes,Base64.DEFAULT);
        //将加密后的密文转为字符串返回
        return aesContent;
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    } catch (NoSuchPaddingException e) {
        e.printStackTrace();
    } catch (InvalidKeyException e) {
        e.printStackTrace();
    } catch (BadPaddingException e) {
        e.printStackTrace();
    } catch (IllegalBlockSizeException e) {
        e.printStackTrace();
    } catch (UnsupportedEncodingException e) {
        e.printStackTrace();
    }
    return null;
}
  • 解密
  /**
 * 密文解密
 *
 * @param key AES密钥
 * @param content  加密后的内容
 * @return
 */
public static String decrypt(SecretKeySpec key, String content) {
    try {
        //根据指定算法生成密码器
        Cipher cipher = Cipher.getInstance("AES");
        //初始化密码器,
        // 第一个参数为密码的操作模式:加密(ENCRYPT_MODE),解密(DECRYPT_MODE)
        //第二个参数为AES密钥
        cipher.init(Cipher.DECRYPT_MODE, key);
        //先将密文进行Base64解码
        byte[] aesBytes = Base64.decode(content,Base64.DEFAULT);
        //将密文进行解密
        byte[] contentBytes = cipher.doFinal(aesBytes);
        //将解密后的内容转成字符串并返回
        return new String(contentBytes,"utf-8");
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    } catch (NoSuchPaddingException e) {
        e.printStackTrace();
    } catch (InvalidKeyException e) {
        e.printStackTrace();
    } catch (BadPaddingException e) {
        e.printStackTrace();
    } catch (IllegalBlockSizeException e) {
        e.printStackTrace();
    } catch (UnsupportedEncodingException e) {
        e.printStackTrace();
    }
    return null;
}

上面就是加解密的代码了,不过需要注意加解密的密钥,也就是上面这两个方法中的第一个参数SecretKeySpec必须是同一个,否则解密会失败。另外也可以根据自己的需求将其保存在本地。

最后在Activity中使用这三个方法:

public class MainActivity extends AppCompatActivity {

private TextView oldView, encryView, decryView;
private SecretKeySpec key; //密钥
private String password = "123456";//随机源种子
private String content = "Hello,玩安卓";//原始内容
private String encryContent;//加密后

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    oldView = (TextView) findViewById(R.id.old_content);
    encryView = (TextView) findViewById(R.id.encry_content);
    decryView = (TextView) findViewById(R.id.decry_content);
    oldView.setText("原内容 : " + content);
    
    //生成密钥
    key = AesEncryptionUtils.createKey(password);
    
    findViewById(R.id.btn_encry).setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            //加密
            encryContent = AesEncryptionUtils.encrypt(key,content);
            encryView.setText("加密后 :" + encryContent);

        }
    });
    findViewById(R.id.btn_decry).setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            //解密
            String decryContent = AesEncryptionUtils.decrypt(key,encryContent);
            decryView.setText("解密后 :" + decryContent);
        }
    });
}

}

效果展示:

aes.gif

结语

如果大家还有什么问题,可以在下面留言,另外推荐一个安卓技术交流群:591683946,大家可以互相学习,共同进步。

相关文章

网友评论

      本文标题:Java实现AES数据加密

      本文链接:https://www.haomeiwen.com/subject/ylbmxftx.html