对称加密算法实践与总结

序言

对称加密算法,加密与解密的密钥是一样的,密钥管理比较困难,容易泄露,一旦泄露就会很容易导致数据不安全。

相关概念

明文: 数据没有进行加密,原始数据信息。

密文: 加密过后得到的数据, 隐藏了原始数据的含义。

加密 : 将明文转为密文的过程。

解密 : 将密文转为明文的过程。

密钥: 是一种参数,是在加密或解密中输入的参数。

对称加密

定义: 指的是加密与解密使用相同的密钥。这种加密方式称为对称加密。

对称加密一般有: DES 、 3DES 、 AES 、 PBE

  • DES(Data Encryption Standard): 数据加密标准,速度较快,适用于加密大量数据的场合。
  • 3DES(Triple DES): 基于DES, 对一块数据用三个不同的密钥进行三次加密,强度更高。
  • AES(Advanced Encryption Standard): 高级加密标准,是下一代的加密算法标准,速度快,安全级别高,支持128、192、256、512位密钥的加密。
  • PBE(Password Based Encryption): 是一种基于口令的加密算法,其特点是使用口令代替了密钥,而口令由用户自己掌管,采用随机数杂凑多重加密等方法保证数据的安全性。

对称加密特征:

  • 加密方和解密方使用同一个密钥。
  • 加密与解密的速度较快。
  • 密钥传输过程不安全,且容易被破解,密钥管理也很麻烦。

代码实现:

DES算法

 /**
 * @program
 * @Desc
 * @Author 游戏人日常
 * @CreateTime 2019/08/11--2:21
 */
public class DesTest {
    //转化格式
    public static final String TRAMSFORMATION = "DES/ECB/PKCS5Padding";
    //算法  DES
    public static final String ALGORITHM = "DES";
    //待加密的源串
    public static final String msg = "helloWorld";
    //密钥
    public static final String key = "123456789";

    public static void main(String args[]) {
        System.out.println("待加密数据: " + msg);
        byte[] encryptStr = encrypt(msg, key);
        System.out.println("加密后以十六进制输出的结果: " + new BigInteger(encryptStr).toString(16));//以十六进制输出
        byte[] decryptStr = decrypt(encryptStr, key);
        System.out.println("解密后的结果:" + new String(decryptStr));
    }

    /**
     *    解密
     * @param encryptionStr  加密的数据
     * @param key  密钥
     * @return
     */
    private static byte[] decrypt(byte[] encryptionStr, String key) {
        try {
            //1.KEY转换
            DESKeySpec desKeySpec = new DESKeySpec(key.getBytes());//实例化DESKey秘钥的相关内容
            SecretKeyFactory factory = SecretKeyFactory.getInstance(ALGORITHM);//实例一个秘钥工厂,指定加密方式
            Key convertKey  = factory.generateSecret(desKeySpec);

            //2.解密    DES/ECB/PKCS5Padding--->算法/工作方式/填充方式
            Cipher cipher = Cipher.getInstance(TRAMSFORMATION);//通过Cipher这个类进行加解密相关操作
            cipher.init(Cipher.DECRYPT_MODE, convertKey );
            byte[] result = cipher.doFinal(encryptionStr);

            return result;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
    /**
     * @param encryptionStr 待加密的串
     * @param key           密钥
     * @return
     */
    public static byte[] encrypt(String encryptionStr, String key) {
        try {
            //1.KEY转换
            DESKeySpec desKeySpec = new DESKeySpec(key.getBytes());//实例化DESKey秘钥的相关内容
            SecretKeyFactory factory = SecretKeyFactory.getInstance(ALGORITHM);//实例一个秘钥工厂,指定加密方式
            Key convertKey  = factory.generateSecret(desKeySpec);

            //2.加密    DES/ECB/PKCS5Padding--->算法/工作方式/填充方式
            Cipher cipher = Cipher.getInstance(TRAMSFORMATION);//通过Cipher这个类进行加解密相关操作
            cipher.init(Cipher.ENCRYPT_MODE, convertKey );
            byte[] result = cipher.doFinal(encryptionStr.getBytes());//输入要加密的内容

            return result;

        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return null;
    }
}

输出结果

待加密数据: helloWorld
加密后以十六进制输出的结果: -60fd73ff69e3352e5e2e976c55e6ed92
解密后的结果:helloWorld

3DES算法

/**
 * @program
 * @Desc
 * @Author 游戏人日常
 * @CreateTime 2019/08/11--14:45
 */
public class DES3Test {

    //转化格式
    public static final String TRAMSFORMATION = "DESEde/ECB/PKCS5Padding";
    //算法  DES
    public static final String ALGORITHM = "DESEde";
    //待加密的源串
    public static final String msg = "helloWorld";
    //密钥
    public static final String key = "1234567812345678123456789";

    public static void main(String[] args) {
        System.out.println("待加密数据: " + msg);
        byte[] encryptStr = encrypt(msg, key);
        System.out.println("加密后以十六进制输出的结果: " + new BigInteger(encryptStr).toString(16));//以十六进制输出
        byte[] decryptStr = decrypt(encryptStr, key);
        System.out.println("解密后的结果:" + new String(decryptStr));
    }

    /**
     * 解密
     *
     * @param encryptionStr 加密的数据
     * @param key           密钥
     * @return
     */
    private static byte[] decrypt(byte[] encryptionStr, String key) {
        try {
            //1.生成KEY
            DESedeKeySpec desKeySpec = new DESedeKeySpec(key.getBytes());//实例化DESKey秘钥的相关内容
            SecretKeyFactory factory = SecretKeyFactory.getInstance(ALGORITHM);//实例一个秘钥工厂,指定加密方式
            Key convertKey  = factory.generateSecret(desKeySpec);

            //2.解密    DES/ECB/PKCS5Padding--->算法/工作方式/填充方式
            Cipher cipher = Cipher.getInstance(TRAMSFORMATION);//通过Cipher这个类进行加解密相关操作
            cipher.init(Cipher.DECRYPT_MODE, convertKey );
            byte[] result = cipher.doFinal(encryptionStr);

            return result;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public static byte[] encrypt(String encryptionStr, String key) {
        try {

            //1.转换KEY
            DESedeKeySpec deSedeKeySpec = new DESedeKeySpec(key.getBytes());
            SecretKeyFactory factory = SecretKeyFactory.getInstance(ALGORITHM);
            Key convertKey = factory.generateSecret(deSedeKeySpec);

            //2.加密
            Cipher cipher = Cipher.getInstance(TRAMSFORMATION);
            cipher.init(Cipher.ENCRYPT_MODE, convertKey);
            byte[] result = cipher.doFinal(encryptionStr.getBytes());
            return result;

        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return null;
    }
}

输出结果

待加密数据: helloWorld
加密后以十六进制输出的结果: -60fd73ff69e3352e5e2e976c55e6ed92
解密后的结果:helloWorld

AES算法

/**
 * @program
 * @Desc
 * @Author 游戏人日常
 * @CreateTime 2019/08/11--15:16
 */
public class AESTest {

    //转化格式
    public static final String TRAMSFORMATION = "AES/ECB/PKCS5Padding";
    //算法  DES
    public static final String ALGORITHM = "AES";
    //待加密的源串
    public static final String msg = "helloWorld";
    //密钥
    public static final String key = "1234567812345678";

    public static void main(String[] args) {
        System.out.println("待加密数据: " + msg);
        byte[] encryptStr = encrypt(msg, key);
        System.out.println("加密后以十六进制输出的结果: " + new BigInteger(encryptStr).toString(16));//以十六进制输出
        byte[] decryptStr = decrypt(encryptStr, key);
        System.out.println("解密后的结果:" + new String(decryptStr));
    }

    /**
     * 解密
     *
     * @param encryptionStr 加密的数据
     * @param key           密钥
     * @return
     */
    private static byte[] decrypt(byte[] encryptionStr, String key) {
        try {
            //1.转换KEY
            Key convertKey = new SecretKeySpec(key.getBytes(), ALGORITHM);

            //2.解密    DES/ECB/PKCS5Padding--->算法/工作方式/填充方式
            Cipher cipher = Cipher.getInstance(TRAMSFORMATION);//通过Cipher这个类进行加解密相关操作
            cipher.init(Cipher.DECRYPT_MODE, convertKey);
            byte[] result = cipher.doFinal(encryptionStr);

            return result;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public static byte[] encrypt(String encryptionStr, String key) {
        try {
            //1.转换KEY
            Key convertKey = new SecretKeySpec(key.getBytes(), ALGORITHM);

            //2.加密
            Cipher cipher = Cipher.getInstance(TRAMSFORMATION);
            cipher.init(Cipher.ENCRYPT_MODE, convertKey);
            byte[] result = cipher.doFinal(encryptionStr.getBytes());

            return result;

        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return null;
    }
}

输出结果

待加密数据: helloWorld
加密后以十六进制输出的结果: -680bb3194a04ff1ece4e28227012ad33
解密后的结果:helloWorld

PBE算法

/**
 * @program
 * @Desc
 * @Author 游戏人日常
 * @CreateTime 2019/08/11--15:55
 */
public class PBETest {
    //转化格式
    public static final String TRAMSFORMATION = "PBEWITHMD5andDES";
    //待加密的源串
    public static final String msg = "helloWorld";
    //密钥
    public static final String key = "123456789";

    public static void main(String args[]) {
        byte[] salt=initSalt();//初始化salt
        System.out.println("待加密数据: " + msg);
        byte[] encryptStr = encrypt(salt,msg,key);
        System.out.println("加密后以十六进制输出的结果: " + new BigInteger(encryptStr).toString(16));//以十六进制输出
        byte[] decryptStr = decrypt(salt,encryptStr, key);
        System.out.println("解密后的结果:" + new String(decryptStr));
    }

     public static byte[] initSalt(){
         SecureRandom secureRandom = new SecureRandom();
         byte[] salt = secureRandom.generateSeed(8);
         return salt;
     }

    /**
     *    解密
     * @param  salt
     * @param encryptionStr  加密的数据
     * @param key   这个是加密用的口令
     * @return
     */
    private static byte[] decrypt(byte[] salt, byte[] encryptionStr, String key) {
        try {
            //1.转换KEY
            PBEKeySpec pbeKeySpec = new PBEKeySpec(key.toCharArray());
            SecretKeyFactory factory = SecretKeyFactory.getInstance(TRAMSFORMATION);
            Key convertKey = factory.generateSecret(pbeKeySpec);
            //2.解密
            PBEParameterSpec parameterSpec = new PBEParameterSpec(salt, 100);//100是你选择迭代的次数
            Cipher cipher = Cipher.getInstance(TRAMSFORMATION);
            cipher.init(Cipher.DECRYPT_MODE, convertKey, parameterSpec);
            byte[] result = cipher.doFinal(encryptionStr);

            return result;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
    /**
	 * 加密
     * @param  salt
     * @param encryptionStr 待加密的串
     * @param key           这个是加密用的口令
     * @return
     */
    public static byte[] encrypt(byte[] salt,String encryptionStr,String key) {
        try {
            //1.转换KEY
            PBEKeySpec pbeKeySpec = new PBEKeySpec(key.toCharArray());
            SecretKeyFactory factory = SecretKeyFactory.getInstance(TRAMSFORMATION);
            Key convertKey = factory.generateSecret(pbeKeySpec);
            //2. 加密
            PBEParameterSpec parameterSpec = new PBEParameterSpec(salt, 100);//100是你选择迭代的次数
            Cipher cipher = Cipher.getInstance(TRAMSFORMATION);
            cipher.init(Cipher.ENCRYPT_MODE, convertKey, parameterSpec);
            byte[] result = cipher.doFinal(encryptionStr.getBytes());

            return result;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}

输出结果

待加密数据: helloWorld
加密后以十六进制输出的结果: 450056595e1fbcc4f35bf855bd18dee2
解密后的结果:helloWorld

总结

  1. 这些对称算法全是JDK自带的API实现,也可以用第三方(BouncyCastle)的实现。
  2. 不同的算法对key的长度有要求,通过查看jdk代码发现DES的key必须大于8,3DES大于24等等。 否则会抛异常:Wrong key size
  3. 这些对称算法的底层原理是怎么实现的本文没有叙述,具体怎么实现请查看其它的资料。

对称算法优缺点

优点

速度快,通常在消息发送方需要加密大量数据时使用,算法公开、计算量小、加密速度快、加密效率高。

缺点

在数据传输前,发送和接收方必须确定好密钥,然后双方都能保存这个密钥,一旦泄露那么数据的传输这个过程就很不安全。

一个游戏技术人,分享Java、Python、H5、Android 等知识。同时会分享游戏行业日常。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值