密码技术学习(5.2)-对称加密在Java中的使用

版权声明:转载请注明出处 https://blog.csdn.net/laozhaishaozuo/article/details/81843625
  • 对称加密在Java中的使用

对称加密在Java中的使用

在之前的文章中,我们已经将要介绍了对称加密(后期链接到前面的文章),现在我们将了解Java对于对称加密的支持。

DES

我们先介绍Java中DES的使用

DESCoder 工具类

import java.security.GeneralSecurityException;

import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;

/**
 * DES 安全编码组件
 *
 * @author shaozuo
 *
 * @version 2018年7月2日
 */
public final class DESCoder {

    public static final String DES = "DES";

    private DESCoder() {

    }

    /**
     * 使用Java 提供的DES 实现<br>
     * 
     * @return 密钥 按照一定编码格式编码的密钥
     * @throws GeneralSecurityException
     */
    public static byte[] initKey() throws GeneralSecurityException {
        return initKey(56);
    }

    /**
     * 生成密钥 使用默认的Provider<br>
     * java只支持56位 <br>
     * 
     * @return 密钥
     * @throws GeneralSecurityException
     */
    public static byte[] initKey(int keySize) throws GeneralSecurityException {
        // 实例化密钥生成器
        KeyGenerator kg = KeyGenerator.getInstance(DES);
        // 初始化
        kg.init(keySize);
        // 生成秘密密钥
        SecretKey secretKey = kg.generateKey();
        // 获得密钥的二进制表示形式
        return secretKey.getEncoded();
    }

    /**
     * 生成密钥 <br>
     * java只支持56位 <br>
     * Bouncy Castle 支持64 位
     * 
     * @return 密钥
     * @throws GeneralSecurityException
     */
    public static byte[] initKey(int keySize, String providerName) throws GeneralSecurityException {
        // 实例化密钥生成器
        KeyGenerator kg = KeyGenerator.getInstance(DES, providerName);
        // 初始化
        kg.init(keySize);
        // 生成秘密密钥
        SecretKey secretKey = kg.generateKey();
        // 获得密钥的二进制表示形式
        return secretKey.getEncoded();
    }
}

测试代码

import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;

import java.security.GeneralSecurityException;
import java.security.InvalidParameterException;
import java.security.Security;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;

import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;

/**
 * DES 测试
 * 
 * @author shaozuo
 *
 */
public class DESTest {

    @Rule
    public ExpectedException thrown = ExpectedException.none();

    /**
     * Java 本身自带的DES算法实现<br>
     * 密钥长度只能是56位,否则会抛出异常
     * 
     * @throws GeneralSecurityException
     */
    @Test
    public void testJdkKeySize() throws GeneralSecurityException {
        // 支持56位密钥
        DESCoder.initKey(56);
        thrown.expect(InvalidParameterException.class);
        thrown.expectMessage("Wrong keysize: must be equal to 56");
        // 不支持64位DES密码
        DESCoder.initKey(64);

    }

    /**
     * BouncyCastle 支持64位DES密钥<br>
     * 
     * @throws GeneralSecurityException
     */
    @Test
    public void testBcKeySize() throws GeneralSecurityException {
        Security.addProvider(new BouncyCastleProvider());
        DESCoder.initKey(64, BouncyCastleProvider.PROVIDER_NAME);
    }

    /**
     * DES 加密解密测试
     * 
     * @throws Exception
     */
    @Test
    public void testEncyptDecypt() throws Exception {
        String raw = "待加密数据";
        byte[] rawData = raw.getBytes();

        byte[] keyData = DESCoder.initKey();
        DESKeySpec desKeySpec = new DESKeySpec(keyData);
        SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance(DESCoder.DES);
        SecretKey secretKey = secretKeyFactory.generateSecret(desKeySpec);

        Cipher cipher = Cipher.getInstance(DESCoder.DES);
        // 加密数据
        cipher.init(Cipher.ENCRYPT_MODE, secretKey);
        byte[] encryptData = cipher.doFinal(rawData);
        // 解密数据
        cipher.init(Cipher.DECRYPT_MODE, secretKey);
        byte[] decryptData = cipher.doFinal(encryptData);
        assertArrayEquals(rawData, decryptData);
        assertEquals(raw, new String(decryptData));
    }
}

AES

接下来我们用代码来使用AES加密算法

工具类

import java.security.GeneralSecurityException;

import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;

/**
 * AES 安全编码组件
 *
 * @author shaozuo
 *
 * @version 2018年7月2日
 */
public final class AESCoder {

    public static final String ALGORITHM_NAME = "AES";

    private AESCoder() {

    }

    /**
     * 使用Java 提供的AES 实现<br>
     * 
     * @return 密钥 按照一定编码格式编码的密钥
     * @throws GeneralSecurityException
     */
    public static byte[] initKey() throws GeneralSecurityException {
        return initKey(128);
    }

    /**
     * 生成密钥 使用默认的Provider<br>
     * Java 支持128、192、256位(需要获取无限制文件) <br>
     * 
     * @return 密钥
     * @throws GeneralSecurityException
     */
    public static byte[] initKey(int keySize) throws GeneralSecurityException {
        // 实例化密钥生成器
        KeyGenerator kg = KeyGenerator.getInstance(ALGORITHM_NAME);
        // 初始化
        kg.init(keySize);
        // 生成秘密密钥
        SecretKey secretKey = kg.generateKey();
        // 获得密钥的二进制表示形式
        return secretKey.getEncoded();
    }

    /**
     * 生成密钥 <br>
     * Java 支持128、192、256位 <br>
     * Bouncy Castle 支持64 位
     * 
     * @return 密钥
     * @throws GeneralSecurityException
     */
    public static byte[] initKey(int keySize, String providerName) throws GeneralSecurityException {
        // 实例化密钥生成器
        KeyGenerator kg = KeyGenerator.getInstance(ALGORITHM_NAME, providerName);
        // 初始化
        kg.init(keySize);
        // 生成秘密密钥
        SecretKey secretKey = kg.generateKey();
        // 获得密钥的二进制表示形式
        return secretKey.getEncoded();
    }
}

测试

import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;

import java.security.GeneralSecurityException;
import java.security.Security;

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

import org.apache.commons.codec.binary.Base64;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.junit.Test;

public class AESTest {

    @Test
    public void test() throws GeneralSecurityException {
        Security.addProvider(new BouncyCastleProvider());
        String raw = "待加密数据";
        byte[] rawData = raw.getBytes();

        byte[] keyData = AESCoder.initKey(256, BouncyCastleProvider.PROVIDER_NAME);
        SecretKeySpec keySpec = new SecretKeySpec(keyData, AESCoder.ALGORITHM_NAME);
        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(keySpec.getAlgorithm());
        SecretKey secretKey = keyFactory.generateSecret(keySpec);

        // 加密解密算法/工作模式/填充方式
        Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
        // 加密数据
        cipher.init(Cipher.ENCRYPT_MODE, secretKey);
        byte[] encryptData = cipher.doFinal(rawData);
        System.out.println(Base64.encodeBase64String(encryptData));
        // 解密数据
        cipher.init(Cipher.DECRYPT_MODE, secretKey);
        byte[] decryptData = cipher.doFinal(encryptData);
        System.out.println(Base64.encodeBase64String(decryptData));
        assertArrayEquals(rawData, decryptData);
        assertEquals(raw, new String(decryptData));

    }
}

参考文章

关于本章内容,参考了一下书籍和文章

  1. Java加密与解密的艺术 链接

本系列其他文章

密码技术学习系列文章

猜你喜欢

转载自blog.csdn.net/laozhaishaozuo/article/details/81843625
今日推荐