加密(3)非对称加密

一、介绍

1、概念

非对称加密,又称现代加密算法,非对称加密是计算机通信安全的基石,保证了加密数据不会被破解。加密和解密使用的是两个不同的密钥,这种算法叫作非对称加密算法

2、示例

首先生成密钥对, 公钥为(5,14),私钥为(11,14);

现在A希望将原文2发送给B:

A使用公钥加密数据. 2的5次方mod 14 = 4 , 将密文4发送给B;

B使用私钥解密数据. 4的11次方mod14 = 2, 得到原文2。

3、和对称加密的比较

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

4、特点

(1)加密和解密使用不同的密钥,且公开密钥和私有密钥是一对。

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

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

(3)处理数据的速度较慢, 因为安全级别高

5、常用算法
  • RSA
  • ECC

二、 RSA

1、使用方法

首先需要生成公钥和密钥对;之后使用一个加密另外一个解密。

复制代码
import org.apache.commons.io.FileUtils;

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;
import java.util.Base64;


public class RsaUtil {

    public static void main(String[] args) throws Exception {
        String input = "测试wtyy666";
        // 加密算法
        String algorithm = "RSA";
        String priPath = "a.pri";
        String pubPath = "a.pub";

        //1、生成密钥对并保存在本地文件中
        generateKeyToFile(algorithm, pubPath, priPath);
        //2、加密
        String s = encryptRSA(algorithm, getPrivateKey(priPath,algorithm), input);
        System.out.println("加密后:"+s);
        // 3、解密
        String s1 = decryptRSA(algorithm, getPublicKey(pubPath,algorithm), s);
        System.out.println("解密后:"+s1);
    }

    //读取私钥
    public static PrivateKey getPrivateKey(String priPath,String algorithm) throws Exception{
        // 将文件内容转为字符串
        String privateKeyString = FileUtils.readFileToString(new File(priPath), Charset.defaultCharset());
        // 获取密钥工厂
        KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
        // 构建密钥规范 进行Base64解码
        PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(Base64.getDecoder().decode(privateKeyString));
        // 生成私钥
        return keyFactory.generatePrivate(spec);
    }

    //读取公钥
    public static PublicKey getPublicKey(String pulickPath,String algorithm) throws Exception{
        // 将文件内容转为字符串
        String publicKeyString = FileUtils.readFileToString(new File(pulickPath), Charset.defaultCharset());
        // 获取密钥工厂
        KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
        // 构建密钥规范 进行Base64解码
        X509EncodedKeySpec spec = new X509EncodedKeySpec(Base64.getDecoder().decode(publicKeyString));
        // 生成公钥
        return keyFactory.generatePublic(spec);
    }

    /**
     * 生成密钥对并保存在本地文件中
     *
     * @param algorithm : 算法
     * @param pubPath   : 公钥保存路径
     * @param priPath   : 私钥保存路径
     * @throws Exception
     */
    private static void generateKeyToFile(String algorithm, String pubPath, String priPath) throws Exception {
        // 获取密钥对生成器
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(algorithm);
        // 获取密钥对
        KeyPair keyPair = keyPairGenerator.generateKeyPair();
        // 获取公钥
        PublicKey publicKey = keyPair.getPublic();
        // 获取私钥
        PrivateKey privateKey = keyPair.getPrivate();
        // 获取byte数组
        byte[] publicKeyEncoded = publicKey.getEncoded();
        byte[] privateKeyEncoded = privateKey.getEncoded();
        // 进行Base64编码
        String publicKeyString = Base64.getEncoder().encodeToString(publicKeyEncoded);
        String privateKeyString = Base64.getEncoder().encodeToString(privateKeyEncoded);
        // 保存文件
        FileUtils.writeStringToFile(new File(pubPath), publicKeyString, Charset.forName("UTF-8"));
        FileUtils.writeStringToFile(new File(priPath), privateKeyString, Charset.forName("UTF-8"));
        System.out.println("生成的共钥: " + publicKeyString);
        System.out.println("生成的私钥: " + privateKeyString);
    }

    /**
     * 解密数据
     *
     * @param algorithm      : 算法
     * @param encrypted      : 密文
     * @param key            : 密钥
     * @return : 原文
     * @throws Exception
     */
    public static String decryptRSA(String algorithm,Key key,String encrypted) throws Exception{
        // 创建加密对象
        // 参数表示加密算法
        Cipher cipher = Cipher.getInstance(algorithm);
        // 私钥进行解密
        cipher.init(Cipher.DECRYPT_MODE,key);
        // 由于密文进行了Base64编码, 在这里需要进行解码
        byte[] decode = Base64.getDecoder().decode(encrypted);
        // 对密文进行解密,不需要使用base64,因为原文不会乱码
        byte[] bytes1 = cipher.doFinal(decode);
        //System.out.println(new String(bytes1));
        return new String(bytes1);

    }
    /**
     * 使用密钥加密数据
     *
     * @param algorithm      : 算法
     * @param input          : 原文
     * @param key            : 密钥
     * @return : 密文
     * @throws Exception
     */
    public static String encryptRSA(String algorithm,Key key,String input) throws Exception{
        // 创建加密对象
        // 参数表示加密算法
        Cipher cipher = Cipher.getInstance(algorithm);
        // 初始化加密
        // 第一个参数:加密的模式
        // 第二个参数:使用私钥进行加密
        cipher.init(Cipher.ENCRYPT_MODE,key);
        // 私钥加密
        byte[] bytes = cipher.doFinal(input.getBytes());
        // 对密文进行Base64编码
        System.out.println(Base64.getEncoder().encodeToString(bytes));
        return Base64.getEncoder().encodeToString(bytes);
    }
}

生成的共钥: MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4QYyI6aTqFZrQrcprgbCE2g60eLKVYBguiPLt7zPT2rCw+13s5c7G7WWjgiJ7UN2rQ+r+aVEKSe8eou/7lb8kEMrbJYJGg8y9KGyQ62ry1/0Rvw5DtHCoSpcu8czTVkB2mhYSCG+BTXaMmsVNICEXR7g4CZ/ILfLCugjNangkQ8iIEFYaLE1ssbcZmXCyA3kTVMqdplHYi1wgd9Vk8tQP77K5joZzb23F5bWZW+8yS+i1gKq1sxipzb8ZG/UMCP6upjqAHh6bgTJa+ORZmT6cXtjW235XK/Jq5NelN/9RGzsHbPSFgvFIayEAgA8WyyR/JCAIqUtj6hjwNG7tOAEfQIDAQAB
生成的私钥: MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDhBjIjppOoVmtCtymuBsITaDrR4spVgGC6I8u3vM9PasLD7XezlzsbtZaOCIntQ3atD6v5pUQpJ7x6i7/uVvyQQytslgkaDzL0obJDravLX/RG/DkO0cKhKly7xzNNWQHaaFhIIb4FNdoyaxU0gIRdHuDgJn8gt8sK6CM1qeCRDyIgQVhosTWyxtxmZcLIDeRNUyp2mUdiLXCB31WTy1A/vsrmOhnNvbcXltZlb7zJL6LWAqrWzGKnNvxkb9QwI/q6mOoAeHpuBMlr45FmZPpxe2Nbbflcr8mrk16U3/1EbOwds9IWC8UhrIQCADxbLJH8kIAipS2PqGPA0bu04AR9AgMBAAECggEACMs038WzPCrXrcj/1nvKIKXwbigttT3G+Hf7MYJoG8wv4A7oK/U2+hWmAvoiW5B3mSNT4Gov75YpolMYnHmeDK828kPle8xcttQ7wuIkMG3e8qsJrihxYDdy6XrLLmj1AxUrdyFyFAKvV8DKjPHWy9cv2nnrBjJv0qnLGy+47kI7J4yR137NGz4TvnfS3IxYi1LGwvI7fi38cNVF11FRCQLlkdUYe0RWQ0RFlAu9G6/87cwLB2YnWiZ6RH+zSGcMK2/M7TPHeBtxEkJnMUjpfTVeOqsf6/XRpELwHtRDr2qfEq4LGCPvX1rQFJ11NpJKnh5MbdAOGwevQXWawrYlawKBgQDubHucFUcIyFJciu7fo3NvsbrXBWbaU6bdXZPPhSsxBfOvCIRmS0I+AqBYwjZVB+gejB3p21LFFjz9PO6ewz5bXTJrB2J8CEJfA8zj/7A2XKCl9po4X6ngDOy5ls0PwkELvnILpgdpW5ZfjEpviOHsXJk+QPHCrtINn1sHcUDeXwKBgQDxnNZidrnGgJxpDJvJtmimci5sbnnfg8Vs/YzJTyPh+9m1OZ23gg4h1mfFBi4wuSHofjD7nLG/TYFeF4BbsY032nBSz30EaSYO4IrO0UxgNGQfFnaCS0hQVr0Rr4na+KpYFr26pIJL+FGCR6iYiYTVhGVDTBLK2+WUEOve/ahSowKBgQCoIVn9lEeWWuUxm0ud6z5xKmzuSkHgfhLykZW1RlxR4reX27K6DCI3ZlS6oqH7zmqSeA50JhS1JNx3W+uNi3NCrHLsZLW/b3eWVzC6K0mQ3DrxLfhM/rDlbVfV/BC5JywFYxQ7QKaDVnGxCVZIVseyjQ4Hh3a06eD4eEKR+fxbkwKBgQDgdWflSY8FDm5AWWpRVpiaKPFf4rJuJ6i9vD+StWcMhkCWz9Ppq3UdkmYM79TxhswthS5UUhn/My3AD+07QhODk/dNt1zZQCYPJCNQR7jAl2t8Rg4KtY2UtUAosf9L4j++XkIcpsA1e5edhJzoOLmi8sBwaLf8pZT+nUnDe7toKQKBgQCxu1yYVjCz1i+sJ3inUOaGZjZ/cOLCxmGzLxpKBMPa6VHVbJZtt+n9hdU+Jxi+U1QIdXLtXdvNrkW9LrXEBvuk7uU6VBZSHmaJ/7iGl52bUuQHQnUW8ZKs30obXq7nW5K5VBcHcJMroms+e7xHS2aNdBVXNtQDCUXL3TAZnrTmVg==
KmeXpGFH77J3wowoZ7g68MDJ6X5GnGocHBhGebYeo6aZUFz3CUK/itbuWPv/mdsYqhLeRASYSUA2qrDxglrH8kxKM8WUTkstGjp1N+flX+bjItaE8sAXTF2k/0Mq3bKqpGJ7XB694CEhiS4YRLZQGgloat7aE+P32ayKbCIM58wgZa2mEFlYCbHmohX7tofsEB6DUf7LBKnYGd/MXGRwxgYPqiR3r/V38aVK4cpMRoJPqxXWsq5i2ZvFkwWXduxNXmrXFwF/7hFxqlMOpLPADFikG9cox7FicLJ3FiGZNxOrdMO/xNyGE9V3PBBwStoLqTjIrvEDPij91cEEbNWh4w==
加密后:KmeXpGFH77J3wowoZ7g68MDJ6X5GnGocHBhGebYeo6aZUFz3CUK/itbuWPv/mdsYqhLeRASYSUA2qrDxglrH8kxKM8WUTkstGjp1N+flX+bjItaE8sAXTF2k/0Mq3bKqpGJ7XB694CEhiS4YRLZQGgloat7aE+P32ayKbCIM58wgZa2mEFlYCbHmohX7tofsEB6DUf7LBKnYGd/MXGRwxgYPqiR3r/V38aVK4cpMRoJPqxXWsq5i2ZvFkwWXduxNXmrXFwF/7hFxqlMOpLPADFikG9cox7FicLJ3FiGZNxOrdMO/xNyGE9V3PBBwStoLqTjIrvEDPij91cEEbNWh4w==
解密后:测试wtyy666
2、测试
(1)私钥加密需要公钥解密

① 先使用私钥加密并且解密:

复制代码
 //2、加密
        String s = encryptRSA(algorithm, getPrivateKey(priPath,algorithm), input);
        System.out.println("加密后:"+s);
        // 3、解密
        String s1 = decryptRSA(algorithm, getPrivateKey(priPath,algorithm), s);
        System.out.println("解密后:"+s1);

运行报错 ,因为私钥加密,只能公钥解密。

② 改为公钥解密则正常运行:

复制代码
String s1 = decryptRSA(algorithm, getPublicKey(pubPath,algorithm), s);
(2)公钥加密需要私钥解密

① 先使用公钥加密并且解密

复制代码
 //2、加密
        String s = encryptRSA(algorithm, getPublicKey(pubPath,algorithm), input);
        System.out.println("加密后:"+s);
        // 3、解密
        String s1 = decryptRSA(algorithm, getPublicKey(pubPath,algorithm), s);
        System.out.println("解密后:"+s1);

同样运行报错

② 改为私钥解密则正常运行:

复制代码
String s1 = decryptRSA(algorithm, getPrivateKey(priPath,algorithm), s);

三、ECC

相关推荐
叶落阁主7 小时前
Tailscale 完全指南:从入门到私有 DERP 部署
运维·安全·远程工作
用户962377954482 天前
DVWA 靶场实验报告 (High Level)
安全
数据智能老司机2 天前
用于进攻性网络安全的智能体 AI——在 n8n 中构建你的第一个 AI 工作流
人工智能·安全·agent
数据智能老司机2 天前
用于进攻性网络安全的智能体 AI——智能体 AI 入门
人工智能·安全·agent
用户962377954482 天前
DVWA 靶场实验报告 (Medium Level)
安全
red1giant_star2 天前
S2-067 漏洞复现:Struts2 S2-067 文件上传路径穿越漏洞
安全
用户962377954483 天前
DVWA Weak Session IDs High 的 Cookie dvwaSession 为什么刷新不出来?
安全
cipher4 天前
ERC-4626 通胀攻击:DeFi 金库的"捐款陷阱"
前端·后端·安全
一次旅行7 天前
网络安全总结
安全·web安全
red1giant_star7 天前
手把手教你用Vulhub复现ecshop collection_list-sqli漏洞(附完整POC)
安全