加密-解密详解

原创
2020/07/28 17:56
阅读数 117

 参考视频: https://www.bilibili.com/video/BV1tz4y197hm

package com.shi.encrypt.ascii;

import com.sun.org.apache.xml.internal.security.utils.Base64;
import org.apache.commons.io.FileUtils;
import org.junit.Test;

import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import java.io.File;
import java.nio.charset.Charset;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;

/**
 * Ascii 编码测试
 *
 * @author shiye
 * @create 2020-07-27 17:25
 */
public class AsciiDemo {

    //每个字节数据再ASCII中都有一个数字对应
    @Test
    public void test1() {
//        char a = 'A';
//        int b = a;
//        //65
//        System.out.println(b);

        String a = "AaZ";
        char[] chars = a.toCharArray();
        for (char aChar : chars) {
            int asciiA = aChar;
            System.out.println(asciiA);
        }
    }

    /**
     * 凯撒加密
     * 就是移位法加密
     * 破解方式:使用概率分析法:默认最高是e
     */
    @Test
    public void kaiserTest() {
        //定义原文
        String input = "Hello World";
        //向右移动3位
        int key = 3;
        char[] chars = input.toCharArray();

        //装新生成的数字
        StringBuilder sb = new StringBuilder();
        for (char aChar : chars) {
            int b = aChar;
            b = b + key;
            char bChar = (char) b;
            sb.append(bChar);
        }
        //加密后的密文为====Khoor#Zruog
        System.out.println("加密后的密文为====" + sb.toString());

        System.out.println("====================================");

        char[] charArray = sb.toString().toCharArray();
        StringBuilder tempA = new StringBuilder();
        for (char charA : charArray) {
            int c = charA;
            c = c - key;
            char charC = (char) c;
            tempA.append(charC);
        }
        //解密后的明文====Hello World
        System.out.println("解密后的明文====" + tempA);
    }

    /**
     * 根据编码格式不一样,对应的字节也不一样
     * 如果是UTF-8: 一个中文对应的是三个字节: -26 -106 -67
     * 如果是GBK: 一个中文对应俩个字节:-54 -87
     * 如果是英文就无所谓编码格式
     *
     * @throws Exception
     */
    @Test
    public void test2() throws Exception {
        String a = "施";
        byte[] aBytes = a.getBytes("GBK");
        for (byte abyte : aBytes) {
            System.out.println(abyte);
        }
    }

    /**
     * 对称加密:DES加密 密钥必须是8位
     * 如果是使用AES进行加密的,需要密码是16位
     * 需要配合base64使用
     * <p>
     * 加密算法/加密模式/填充模式
     * DES
     * DES/ECB/PKCS5Padding  默认方式
     * DES/ECB/NoPadding
     * DES/CBC/PKCS5Padding
     * DES/CBC/NoPadding
     * <p>
     * AES
     * AES/ECB/PKCS5Padding  默认方式
     * AES/ECB/NoPadding
     * AES/CBC/PKCS5Padding
     * AES/CBC/NoPadding
     */
    @Test
    public void testDES() throws Exception {
        //原文
        String input = "施爷";
        System.out.println("明文==" + input);

        //定义key,密钥必须是8位
        String key = "12345678";
        //算法
        String transformation = "DES";
//        String transformation = "DES/ECB/PKCS5Padding";
//        String transformation = "DES/CBC/PKCS5Padding";
        //再使用CBC加密模式的时候需要使用该iv变量,IV必须是8个字节
//        IvParameterSpec iv = new IvParameterSpec("12345678".getBytes());
        //如果是使用AES进行加密的,需要密码是16位
//        String transformation = "AES";
        //创建加密对象
        Cipher cipher = Cipher.getInstance(transformation);
        //加密类型
        String algorithm = "DES";
        /**
         * 创建加密规则
         * 第一参数: 表示key的字节
         * 第二个参数:表示加密的类型
         */
        SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(), algorithm);

        /**
         * 进行加密初始化
         * 第一个表示模式,加密模式,解密模式
         * 第二个参数表示:加密的规则
         */
//        cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec,iv);
        cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);

        /**
         * 调用加密方法
         * 参数表示原文的字节数组
         */
        byte[] bytes = cipher.doFinal(input.getBytes());

//        for (byte aByte : bytes) {
//            System.out.println(aByte);
//        }
//        System.out.println(new String(bytes));//a&f�B
        /**
         * 需要配合base64进行加密,否则会出现乱码
         * 如果字节不够3个使用=号补齐
         */
        String encode = Base64.encode(bytes);
        System.out.println("加密==" + encode);//DmEmZoQXQhI=


        System.out.println("***************解密*******************");
        //创建解密对象
        Cipher cipher1 = Cipher.getInstance(transformation);
        /**
         * 创建解密规则
         * 第一参数: 表示key的字节
         * 第二个参数:表示解密的类型
         */
        SecretKeySpec sks = new SecretKeySpec(key.getBytes(), algorithm);
        //解密对象初始化
        cipher1.init(Cipher.DECRYPT_MODE, sks);
        //解码
        byte[] decode = Base64.decode(encode);
        //解密
        byte[] bytes1 = cipher1.doFinal(decode);
        System.out.println("解密==" + new String(bytes1));
    }

    /**
     * Base64位测试,
     * 原理:三个字节位一组,总共24位,把24位拆成4组,每组6个字节,高位补齐2个字节0
     * 根据base64位编码表进行编排,生成信的字符串,
     * 不足三个字节的使用=号补齐
     */
    @Test
    public void base64Test() throws Exception {
        System.out.println(Base64.encode("1".getBytes()));//MQ==

        System.out.println(Base64.encode("12".getBytes()));//MTI=

        System.out.println(Base64.encode("123".getBytes()));//MTIz
        //汉字utf-8编码,就是三个字节
        System.out.println(Base64.encode("施".getBytes()));//5pa9
        //如果是使用GBK编码就是俩个字节
        System.out.println(Base64.encode("施".getBytes("GBK")));//yqk=
    }

    /**
     * 消息摘要/数字摘要
     * 算法:MD5
     * SHA-1
     * SHA-256
     * SHA-512
     */
    @Test
    public void messageDigest() throws NoSuchAlgorithmException {
        //原文
        String input = "施爷";
        //算法
        String algorithm = "MD5";
        //创建消息摘要对象
        MessageDigest messageDigest = MessageDigest.getInstance(algorithm);
        //执行消息摘要进行加密
        byte[] digest = messageDigest.digest(input.getBytes());
        //使用base64进行转码
        System.out.println("Base64编码后的值为:" + Base64.encode(digest));//AsK7qXM7045eqFc2jILPBw==

        //===================================
        //直接转成16进制输出结果
        for (byte b : digest) {
            //把密文转成16进制
            String hexString = Integer.toHexString(b & 0Xff);
            if (hexString.length() == 1) {
                hexString = "0" + hexString;
            }
            System.out.print(hexString);
        }
    }


    /**
     * 非对称加密:RSA   ECC
     * RSA 加密算法
     * 想单独生成 PrivateKey 对象 可以使用 KeyFactory
     * PublicKey 同上
     */
    @Test
    public void RSAtest() throws Exception {
        String input = "施爷";
        //使用的加密算法
        String algorithm = "RSA";
        //KeyPairGenerator:密钥对生成器对象
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(algorithm);
        //生成密钥对
        KeyPair keyPair = keyPairGenerator.generateKeyPair();

        //===私钥
        PrivateKey aPrivate = keyPair.getPrivate();
        byte[] encoded = aPrivate.getEncoded();
        String privateKey = Base64.encode(encoded);
        System.out.println("私钥为==" + privateKey);
        FileUtils.writeStringToFile(new File("privateKey.pub"), privateKey, Charset.forName("UTF-8"));

        //===公钥
        PublicKey aPublic = keyPair.getPublic();
        byte[] encoded1 = aPublic.getEncoded();
        String publicKey = Base64.encode(encoded1);
        System.out.println("公钥为==" + publicKey);
        FileUtils.writeStringToFile(new File("publicKey.pri"), publicKey, Charset.forName("UTF-8"));

        /*======================使用私钥加密======================*/
        //创建加密对象
        Cipher cipher = Cipher.getInstance(algorithm);
        cipher.init(Cipher.ENCRYPT_MODE, aPrivate);
        byte[] doFinal = cipher.doFinal(input.getBytes());
        String encode = Base64.encode(doFinal);
        System.out.println("加密后的值为===" + encode);

        /*======================使用公钥解密======================*/
        Cipher cipher2 = Cipher.getInstance(algorithm);
        cipher2.init(Cipher.DECRYPT_MODE, aPublic);
        byte[] doFinal2 = cipher2.doFinal(Base64.decode(encode));
        System.out.println("解密后的值为===" + new String(doFinal2));
    }


    /**
     * 数字证书
     */
    @Test
    public void test22() throws Exception {
        String input = "施爷";
        //使用的加密算法
        String algorithm = "RSA";
        String privateKeyStr = "MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAKdzMj8aAS28BIH6qGIB7+O0z6bu\n" +
                "ujjYJlBhFbtt+Ai9Mm90+rQq7cnc0g7FGAGsBvtfoF+BEKLUNMl6LkGsXM8Sz42P+UWQGslhWYqW\n" +
                "Wo4f7PyCVNlLEcsRgt43JnFQ1yUbtttMKHs8whYcAgFaIyEdGw4h8aGffEVA0VxkshCHAgMBAAEC\n" +
                "gYBOyOmEPQT+8q6gRUJCUqz+0wy8eygNJM3qFbO26we/fN0lCcIHUQduacI/hsZDyx/B1/1J0hz0\n" +
                "r6lifmUTKzjCxKvxpvQFa0iM3njqNX/z+tOpK9RX+awIW7syACbZG4ZCwCPSflB/3uoBYHT4oY5/\n" +
                "WumWX1Berb8WUU1jHZ8SYQJBAOsbXsh4IubAdzmerYoKh5RWEwxF6nHd58XRQq6DnKWvRN/LNUsF\n" +
                "fTDodFkhpC2VFSMxaNSelboYRvXON59rWzECQQC2VKVgu8moqfrS11fEwQ6Iq4sG+mt08/GT2BUZ\n" +
                "yz5z6vXCK+cTjRf4hgR4oGC01/ZlL8OhiUsgA8cprmHoiMk3AkA5/1N/cptxfxMqRKmcvwI5Jo6m\n" +
                "XWz7T/mIBBpGALOY78a2ymNIMX9znDRvdGwSzo8bUmoA4WogMTL4GjoAerRRAkAksXI6vm/97n9Y\n" +
                "0ReLtCJ9pLAs7laTycgTLchJUZq271EYC4fManepfycFM5liq5edk3g2WQ/yWHBLVhnEF0sPAkA7\n" +
                "B/cOKB4Z0HkUSMEL0P8OT7N/afZMzv/KjpTAMKUfrgNptSTG5y2TcGEv4Bktj/+4SAegnVKF98oM\n" +
                "+Vh4i9lw";
        String publiceKeyStr = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCnczI/GgEtvASB+qhiAe/jtM+m7ro42CZQYRW7\n" +
                "bfgIvTJvdPq0Ku3J3NIOxRgBrAb7X6BfgRCi1DTJei5BrFzPEs+Nj/lFkBrJYVmKllqOH+z8glTZ\n" +
                "SxHLEYLeNyZxUNclG7bbTCh7PMIWHAIBWiMhHRsOIfGhn3xFQNFcZLIQhwIDAQAB";


        //创建key工厂
        KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
        /*===========================生成私钥对象===========================*/
        //私钥规则
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(Base64.decode(privateKeyStr));
        PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
//        System.out.println("私钥对象=" + privateKey);

        /*===========================生成公钥对象===========================*/
        //公钥规则
        X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(Base64.decode(publiceKeyStr));
        PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
//        System.out.println("公钥对象=" + publicKey);


        /*------------------------生成数字签名------------------------------*/
        //获取签名对象
        Signature signature = Signature.getInstance("sha256withrsa");
        //初始化签名
        signature.initSign(privateKey);
        //传入原文
        signature.update(input.getBytes());
        //开始签名
        byte[] sign = signature.sign();
        String encode_sign = Base64.encode(sign);
        System.out.println("生成的签名为=" + encode_sign);


        /*------------------------校验数字签名------------------------------*/
        //获取签名对象
        Signature signature2 = Signature.getInstance("sha256withrsa");
        //初始化校验
        signature2.initVerify(publicKey);
        //传入原文
        signature2.update(input.getBytes());
        //开始和签名对比,校验签名
        boolean verify = signature2.verify(Base64.decode(encode_sign));
        System.out.println("验签的结果为=" + verify);
    }

}

 

展开阅读全文
打赏
0
0 收藏
分享
加载中
更多评论
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部