AES 代码实现

1 分组加密
首先了解下什么是分组加密:分组密码是将明文消息编码表示后的数字(简称明文数字)序列,划分成长度为n的组(可看成长度为n的矢量),每组分别在密钥的控制下变换成等长的输出数字(简称密文数字)序列。

这里写图片描述
3 ECB的加密方式
http://zh.wikipedia.org/wiki/%E5%9D%97%E5%AF%86%E7%A0%81%E7%9A%84%E5%B7%A5%E4%BD%9C%E6%A8%A1%E5%BC%8F

电码本模式:这种模式是将整个明文分成若干段相同的小段,然后对每一小段进行加密
这里写图片描述
将明文的各个分组独立的使用相同的密钥进行加密,这种方式加密时各分组的加密独立进行互不干涉,因而可并行进行。同样因为各分组独立加密的缘故,相同的明文分组加密之后具有相同的密文。该模式容易暴露明文分组的统计规律和结构特征。不能防范替换攻击。

优点:

1.简单;

2.有利于并行计算;

3.误差不会被传送;

缺点:

1.不能隐藏明文的模式;

2.可能对明文进行主动攻击;

2 CBC加密模式
密码分组链接模式:这种模式是先将明文切分成若干小段,然后每一小段与初始块或者上一段的密文段进行异或运算后,再与密钥进行加密;
这里写图片描述
优点:

1.不容易主动攻击,安全性好于ECB,适合传输长度长的报文,是SSL、IPSec的标准。

缺点:

1.不利于并行计算;

2.误差传递;

3.需要初始化向量IV

3 编程实现

package com.zhy.concurrency.cyclic;

import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

public class AesEncryption {



    // 使用CBC加密需要使用添加一个向量

    // 此处不符合安全规范:分组密码算法使用到的IV值,必须不可预测;推荐使用安全的随机数



    public static void main(String[] args) {

              // TODO Auto-generated method stub

              String aes_key = "0123456789abcdef";

              // 此处密钥硬编码

              String strSrc = "0123456789abcdefadmin";

              // 数据明文,敏感信息泄露

              System.out.println(strSrc);

              String encrypt_code = AesEncrypt_test(strSrc, aes_key);

              System.out.println(encrypt_code);

              String decrypt_code = AesDncrypt_test(encrypt_code, aes_key);

              System.out.println(decrypt_code);

              // log打印,敏感信息泄露

    }



    // 使用CBC的加密算法,要求密钥为16byte

    public static String AesEncrypt_test(String content, String aes_key) {

              try {

                       byte[] raw = aes_key.getBytes();

                       SecretKeySpec secretkey = new SecretKeySpec(raw, "AES");

                       Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");



                       SecureRandom random = new SecureRandom();

                       byte ivParameter[] = new byte[16];

                       random.nextBytes(ivParameter);



                       System.out.println(parseByte2HexStr(ivParameter));



                       IvParameterSpec ivparam = new IvParameterSpec(ivParameter);

                       cipher.init(Cipher.ENCRYPT_MODE, secretkey, ivparam);

                       byte[] encrypted = cipher.doFinal(content.getBytes());

                       return parseByte2HexStr(ivParameter) + parseByte2HexStr(encrypted);

                       //将IV生成的结果附在加密数据前16bytes,每次都使用不同的iv



              } catch (InvalidKeyException | NoSuchAlgorithmException

                                | NoSuchPaddingException | InvalidAlgorithmParameterException

                                | IllegalBlockSizeException | BadPaddingException e) {

                       // TODO Auto-generated catch block

                       e.printStackTrace();

              }

              return null;

    }



    public static String AesDncrypt_test(String content, String aes_key) {

              try {

                       byte[] raw = aes_key.getBytes();

                       SecretKeySpec secretkey = new SecretKeySpec(raw, "AES");

                       Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");





                       String ivParameter = content.substring(0,32);

                  //取前16byte作为cbc解密的iv向量

                       System.out.println(ivParameter);



                       IvParameterSpec ivparam = new IvParameterSpec(

                                          parseHexStr2Byte(ivParameter));

                       cipher.init(Cipher.DECRYPT_MODE, secretkey, ivparam);

                       byte[] decrypted = cipher.doFinal(parseHexStr2Byte(content.substring(32)));

                       return new String(decrypted);

              } catch (InvalidKeyException | NoSuchAlgorithmException

                                | NoSuchPaddingException | InvalidAlgorithmParameterException

                                | IllegalBlockSizeException | BadPaddingException e) {

                       // TODO Auto-generated catch block

                       e.printStackTrace();

              }

              return null;

    }

    /**

     * 将2进制转换为16进制

     * 

     * @param hexStr

     * @return

     */

    private 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

     */

    private 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;

}
}

AES(Advanced Encryption Standard)是一种对称加密算法,它的密钥长度可以是 128、192 或 256 位。下面是 JAVA 实现 AES 加密和解密的代码: ```java import javax.crypto.Cipher; import javax.crypto.KeyGenerator; import javax.crypto.SecretKey; import javax.crypto.spec.SecretKeySpec; import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; import java.util.Base64; public class AES { public static void main(String[] args) throws Exception { String plainText = "Hello, world!"; String password = "1234567890abcdef"; String cipherText = encrypt(plainText, password); System.out.println(cipherText); String decryptedText = decrypt(cipherText, password); System.out.println(decryptedText); } public static String encrypt(String plainText, String password) throws Exception { byte[] keyBytes = password.getBytes(); KeyGenerator keyGenerator = KeyGenerator.getInstance("AES"); SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG"); secureRandom.setSeed(keyBytes); keyGenerator.init(128, secureRandom); SecretKey secretKey = keyGenerator.generateKey(); byte[] enCodeFormat = secretKey.getEncoded(); SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES"); Cipher cipher = Cipher.getInstance("AES");// 创建密码器 byte[] byteContent = plainText.getBytes("utf-8"); cipher.init(Cipher.ENCRYPT_MODE, key);// 初始化 byte[] result = cipher.doFinal(byteContent); return Base64.getEncoder().encodeToString(result); } public static String decrypt(String cipherText, String password) throws Exception { byte[] keyBytes = password.getBytes(); KeyGenerator keyGenerator = KeyGenerator.getInstance("AES"); SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG"); secureRandom.setSeed(keyBytes); keyGenerator.init(128, secureRandom); SecretKey secretKey = keyGenerator.generateKey(); byte[] enCodeFormat = secretKey.getEncoded(); SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES"); Cipher cipher = Cipher.getInstance("AES");// 创建密码器 cipher.init(Cipher.DECRYPT_MODE, key);// 初始化 byte[] result = cipher.doFinal(Base64.getDecoder().decode(cipherText)); return new String(result, "utf-8"); } } ``` 上述代码中,`encrypt()` 方法实现AES 加密,`decrypt()` 方法实现AES 解密。其中,加密过程主要分为以下几个步骤: 1. 将密码转换为字节数组,并使用 `KeyGenerator` 生成密钥。 2. 获取密钥的字节数组,并根据该数组创建一个 `SecretKeySpec` 对象。 3. 创建 `Cipher` 对象,并使用 `SecretKeySpec` 对象初始化密码器。 4. 将明文转换为字节数组,并调用 `doFinal()` 方法进行加密。 5. 将加密后的字节数组进行 Base64 编码,返回密文字符串。 解密过程与加密过程类似,只不过需要将加密模式改为解密模式,同时需要将密文进行 Base64 解码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值