加解密简要

对称加密

概述

​ 采用单钥密码系统的加密方法,同一个密钥可以同时用作信息的加密和解密,这种加密方法称为对称加密,也称为单密钥加密。

常用算法

  • DES : Data Encryption Standard,即数据加密标准,是一种使用密钥加密的块算法,1977年被美国联邦政府的国家标准局确定为联邦资料处理标准(FIPS),并授权在非密级政府通信中使用,随后该算法在国际上广泛流传开来。
  • AES : Advanced Encryption Standard, 高级加密标准 .在密码学中又称Rijndael加密法,是美国联邦政府采用的一种区块加密标准。这个标准用来替代原先的DES,已经被多方分析且广为全世界所使用。

加密模式

ECB/CBC/CFB/OFB/CTR

填充模式

​ 当需要按块处理的数据, 数据长度不符合块处理需求时, 按照一定的方法填充满块长的规则。

  • NoPadding

    • 不填充.
    • 在DES加密算法下, 要求原文长度必须是8byte的整数倍
    • 在AES加密算法下, 要求原文长度必须是16byte的整数倍
  • PKCS5Padding

    • 数据块的大小为8位, 不够就补足
  • Tips

    • 默认情况下, 加密模式和填充模式为 : ECB/PKCS5Padding
    • 如果使用CBC模式, 在初始化Cipher对象时, 需要增加参数, 初始化向量IV : IvParameterSpec iv = new IvParameterSpec(key.getBytes());

加密模式和填充模式:

AES/CBC/NoPadding (128)
AES/CBC/PKCS5Padding (128)
AES/ECB/NoPadding (128)
AES/ECB/PKCS5Padding (128)
DES/CBC/NoPadding (56)
DES/CBC/PKCS5Padding (56)
DES/ECB/NoPadding (56)
DES/ECB/PKCS5Padding (56)
DESede/CBC/NoPadding (168)
DESede/CBC/PKCS5Padding (168)
DESede/ECB/NoPadding (168)
DESede/ECB/PKCS5Padding (168)
RSA/ECB/PKCS1Padding (1024, 2048)
RSA/ECB/OAEPWithSHA-1AndMGF1Padding (1024, 2048)
RSA/ECB/OAEPWithSHA-256AndMGF1Padding (1024, 2048)

Java 算法实现

DES 算法

密钥和偏移向量:8字节

package com.wyj.Symmetric;

import com.sun.org.apache.xml.internal.security.utils.Base64;

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;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;

// 对称加密算法:DES加解密
public class DES_Arithmetic {
    public static void main(String[] args) throws Exception {
        // 原文
        String input = "ac";
        // DES密钥:8字节
        String key = "12345678";
        // 转换:算法 或 算法/模式/填充
            // DES 或 DES/CBC/PKCS5Padding
            // 只填算法时,默认模式/填充为 /EBC/PKCS5Padding
        String transformation = "DES/ECB/PKCS5Padding";
        // 算法
        String algorithm = "DES";

        System.out.println("原文:" + input);
        String encode = encryptDES(input, key, transformation, algorithm);
        System.out.println("加密:" + encode);
        String des = dncryptDES(encode, key, transformation, algorithm);
        System.out.println("解密:" + des);

    }

    /**
     * 使用DES加密数据
     *
     * @param input          : 原文
     * @param key            : 密钥(DES,密钥的长度必须是8个字节)
     * @param transformation : 获取Cipher对象的算法
     * @param algorithm      : 获取密钥的算法
     * @return : 密文
     * @throws Exception
     */
    private static String encryptDES(String input, String key, String transformation, String algorithm) throws Exception {
        // 加密对象
        Cipher cipher = Cipher.getInstance(transformation);
        // 创建加密规则
            // 第一个参数key的字节
            // 第二个参数表示加密算法
        SecretKeySpec sks = new SecretKeySpec(key.getBytes(), algorithm);
//        // 初始向量,参数表示跟谁进行异或,初始向量的长度必须是8位
//        IvParameterSpec iv = new IvParameterSpec("87654321".getBytes());
//        cipher.init(Cipher.ENCRYPT_MODE,sks,iv);
        // 初始化加密模式和算法
            // ENCRYPT_MODE:加密模式
            // DECRYPT_MODE: 解密模式
        cipher.init(Cipher.ENCRYPT_MODE,sks);
        // 加密
        byte[] bytes = cipher.doFinal(input.getBytes());
        // 输出加密后的数据
        String encode = Base64.encode(bytes);
        return encode;
    }

    /**
     * 使用DES解密
     *
     * @param input          : 密文
     * @param key            : 密钥
     * @param transformation : 获取Cipher对象的算法
     * @param algorithm      : 获取密钥的算法
     * @throws Exception
     * @return: 原文
     */
    private static String dncryptDES(String input, String key, String transformation, String algorithm) throws Exception {
        // 1,获取Cipher对象
        Cipher cipher = Cipher.getInstance(transformation);
        // 指定密钥规则
        SecretKeySpec sks = new SecretKeySpec(key.getBytes(), algorithm);
//        IvParameterSpec iv = new IvParameterSpec("87654321".getBytes());
//        cipher.init(Cipher.DECRYPT_MODE, sks,iv);
        cipher.init(Cipher.DECRYPT_MODE, sks);
        // 3. 解密
        byte[] bytes = cipher.doFinal(Base64.decode(input));

        return new String(bytes);
    }
}

AES 算法

密钥和偏移向量:16字节

package com.wyj.Symmetric;

import com.sun.org.apache.xml.internal.security.utils.Base64;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

// 对称加密算法:AES加解密
public class AES_Arithmetic {
    public static void main(String[] args) throws Exception {
        // 原文
        String input = "ac";
        // AES密钥:16字节
        String key = "1234567812345678";
        // 转换:算法 或 算法/模式/填充
            // DES 或 DES/CBC/PKCS5Padding
            // 只填算法时,默认模式/填充为 /EBC/PKCS5Padding
        String transformation = "AES/CBC/PKCS5Padding";
        // 算法
        String algorithm = "AES";

        System.out.println("原文:" + input);
        String encode = encryptDES(input, key, transformation, algorithm);
        System.out.println("加密:" + encode);
        String des = dncryptDES(encode, key, transformation, algorithm);
        System.out.println("解密:" + des);

    }

    /**
     * 使用DES加密数据
     *
     * @param input          : 原文
     * @param key            : 密钥(AES,密钥的长度必须是16个字节)
     * @param transformation : 获取Cipher对象的算法
     * @param algorithm      : 获取密钥的算法
     * @return : 密文
     * @throws Exception
     */
    private static String encryptDES(String input, String key, String transformation, String algorithm) throws Exception {
        // 加密对象
        Cipher cipher = Cipher.getInstance(transformation);
        // 创建加密规则
            // 第一个参数key的字节
            // 第二个参数表示加密算法
        SecretKeySpec sks = new SecretKeySpec(key.getBytes(), algorithm);
        // 初始向量,参数表示跟谁进行异或,初始向量的长度必须是16位
        IvParameterSpec iv = new IvParameterSpec("8765432112345678".getBytes());
        cipher.init(Cipher.ENCRYPT_MODE,sks,iv);
        // 初始化加密模式和算法
            // ENCRYPT_MODE:加密模式
            // DECRYPT_MODE: 解密模式
//        cipher.init(Cipher.ENCRYPT_MODE,sks);
        // 加密
        byte[] bytes = cipher.doFinal(input.getBytes());
        // 输出加密后的数据
        String encode = Base64.encode(bytes);
        return encode;
    }

    /**
     * 使用DES解密
     *
     * @param input          : 密文
     * @param key            : 密钥
     * @param transformation : 获取Cipher对象的算法
     * @param algorithm      : 获取密钥的算法
     * @throws Exception
     * @return: 原文
     */
    private static String dncryptDES(String input, String key, String transformation, String algorithm) throws Exception {
        // 1,获取Cipher对象
        Cipher cipher = Cipher.getInstance(transformation);
        // 指定密钥规则
        SecretKeySpec sks = new SecretKeySpec(key.getBytes(), algorithm);
        IvParameterSpec iv = new IvParameterSpec("8765432112345678".getBytes());
        cipher.init(Cipher.DECRYPT_MODE, sks,iv);
//        cipher.init(Cipher.DECRYPT_MODE, sks);
        // 3. 解密
        byte[] bytes = cipher.doFinal(Base64.decode(input));

        return new String(bytes);
    }
}

非对称加密

概述

① 非对称加密算法又称现代加密算法

② 非对称加密是计算机通信安全的基石,保证了加密数据不会被破解

③ 与对称加密算法不同,非对称加密算法需要两个密钥:公开密钥(publickey)私有密(privatekey)

④ 公开密钥和私有密钥是一对

⑤ 如果用公开密钥对数据进行加密,只有用对应的私有密钥才能解密

⑥ 如果用私有密钥对数据进行加密,只有用对应的公开密钥才能解密

⑦ 因为加密和解密使用的是两个不同的密钥,所以这种算法叫作非对称加密算法

常用算法

RSAElgamal、背包算法、Rabin、D-H、ECC(椭圆曲线加密算法)。

Java 算法实现

package com.wyj.Asymmetry;

import com.sun.org.apache.xml.internal.security.utils.Base64;

import javax.crypto.Cipher;
import java.security.*;

public class Arithmetic {
    public static void main(String[] args) throws Exception {
        // 加密算法
        String algorithm = "RSA";
        // 创建密钥对生成器对象
        KeyPairGenerator pairGenerator = KeyPairGenerator.getInstance(algorithm);
        // 生成密钥对
        KeyPair keyPair = pairGenerator.generateKeyPair();
        // 生成私钥
        PrivateKey privateKey = keyPair.getPrivate();
        // 生成公钥
        PublicKey publicKey = keyPair.getPublic();
        // 获取私钥字节数组
        byte[] privateKeyEncoded  = privateKey.getEncoded();
        // 获取公钥字节数组
        byte[] publicKeyEncoded = publicKey.getEncoded();
        // 对公钥,私钥进行base64编码
        String privateKeyString  = Base64.encode(privateKeyEncoded);
        String publicKeyString   = Base64.encode(publicKeyEncoded);
        System.out.println("私钥:" + privateKeyString);
        System.out.println("公钥:" + publicKeyString);

        // 原文
        String input = "ace";
        // 创建加密对象
        Cipher cipher = Cipher.getInstance(algorithm);
        // 初始化加密
            // 第一个参数:加密的模式
            // 第二个参数:使用私钥或公钥进行加密
        cipher.init(Cipher.ENCRYPT_MODE, privateKey);
        // 执行加密
        byte[] bytes = cipher.doFinal(input.getBytes());
        System.out.println("加密:===");
        System.out.println(new String(bytes));
        // 公钥或私钥进行解密
        cipher.init(Cipher.DECRYPT_MODE,publicKey);
        // 对密文进行解密,不需要使用base64,因为原文不会乱码
        byte[] bytes1 = cipher.doFinal(bytes);
        System.out.println("解密:===");
        System.out.println(new String(bytes1));
    }



}

数字摘要算法

概述

​ 消息摘要算法的主要特征是加密过程不需要密钥,并且经过加密的数据无法被解密,目前可以被解密逆向的只有CRC32算法,只有输入相同的明文数据经过相同的消息摘要算法才能得到相同的密文。

​ 消息摘要算法是密码学算法中非常重要的一个分支,它通过对所有数据提取指纹信息以实现数据签名、数据完整性校验等功能,由于其不可逆性,有时候会被用做敏感信息的加密。消息摘要算法也被称为哈希(Hash)算法或散列算法。

任何消息经过散列函数处理后,都会获得唯一的散列值,这一过程称为 “消息摘要”,其散列值称为 “数字指纹”,其算法自然就是 “消息摘要算法”了。

特点

  • 无论输入的消息有多长,计算出来的消息摘要的长度总是固定的。
  • 消息摘要看起来是“随机的”。一般地,只要输入的消息不同,对其进行摘要以后产生的摘要消息也必不相同;但相同的输入必会产生相同的输出
  • 消息摘要函数是无 陷门 的单向函数,即只能进行正向的信息摘要,而无法从摘要中恢复出任何的消息,甚至根本就找不到任何与原信息相关的信息。(不可逆)
  • 好的摘要算法,没有人能从中找到“碰撞”,虽然“碰撞”是肯定存在的。即对于给定的一个摘要,不可能找到一条信息使其摘要正好是给定的

常用算法

包含MD系列、SHA系列、MAC系列。

MD系列:

  • 包括:MD2,MD4,MD5

SHA系列:

  • 包括:SHA-1,SHA-2(SHA-224,SHA-256,SHA-384,SHA-512)

MAC系列:

  • HMAC(keyed-Hash Message Authentication Code):含有密钥的散列函数算法

  • 包含了MD和SHA两个系列的消息摘要算法,融合了MD,SHA:

    • MD系列:HmacMD2,HmacMD4,HmacMD5
    • SHA系列:HmacSHA1,HmacSHA224,HmacSHA256,HmacSHA38,HmacSHA512

Java 算法实现

package com.wyj.Symmetric.MessageDigest;

import com.sun.org.apache.xml.internal.security.utils.Base64;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

public class Arithmetic {
    public static void main(String[] args) throws Exception {
        // 原文
        String input = "ace";

        encrypt(input, "MD5");
        encrypt(input, "SHA-1");
        encrypt(input, "SHA-256");
        encrypt(input, "SHA-512");
        
    }

    /**
     *
     * @param input 原文
     * @param algorithm  加密算法
     * @return
     * @throws Exception
     */
    private static String encrypt(String input, String algorithm) throws Exception {
        System.out.println("原文:" + input);
        // 获取数字摘要对象
        MessageDigest messageDigest = MessageDigest.getInstance(algorithm);
        // 获取消息数字摘要的字节数组
        byte[] digest = messageDigest.digest(input.getBytes());
        String encode = Base64.encode(digest);
        System.out.println( algorithm + "加密:" + encode);
        return toHex(digest);
    }

    private static String toHex(byte[] digest) {
        StringBuilder sb = new StringBuilder();
        for (byte b : digest) {
            String s = Integer.toHexString(b & 0xff);
            if (s.length() == 1){
                s = "0" + s;
            }
            sb.append(s);
        }
        System.out.println("十六进制:" + sb.toString());
        return sb.toString();
    }

}
posted @ 2021-06-27 10:42  Swift_十万伏特  阅读(421)  评论(0编辑  收藏  举报