找回密码
 立即注册
  • QQ空间
  • 回复
  • 收藏

对称加密算法实践与总结

admin 2019-8-11 17:07 228人围观 C++相关



序言


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

相关概念


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

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

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

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

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

对称加密


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

对称加密一般有: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. 这些对称算法的底层原理是怎么实现的本文没有叙述,具体怎么实现请查看其它的资料。

对称算法优缺点

优点


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

缺点


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

----------------------------------------------------------------------------------------------------------------------
我们尊重原创,也注重分享,文章来源于微信公众号:游戏人日常,建议关注公众号查看原文。如若侵权请联系qter@qter.org。
----------------------------------------------------------------------------------------------------------------------

鲜花

握手

雷人

路过

鸡蛋

yafeilinux和他的朋友们微信公众号二维码

微信公众号

专注于Qt嵌入式Linux开发等。扫一扫立即关注。

Qt开源社区官方QQ群二维码

QQ交流群

欢迎加入QQ群大家庭,一起讨论学习!

我有话说......