加密(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

相关推荐
jjyangyou33 分钟前
物联网核心安全系列——物联网安全需求
物联网·算法·安全·嵌入式·产品经理·硬件·产品设计
AltmanChan1 小时前
大语言模型安全威胁
人工智能·安全·语言模型
马船长1 小时前
红帆OA iorepsavexml.aspx文件上传漏洞
安全
hikktn9 小时前
如何在 Rust 中实现内存安全:与 C/C++ 的对比分析
c语言·安全·rust
23zhgjx-NanKon11 小时前
华为eNSP:QinQ
网络·安全·华为
23zhgjx-NanKon11 小时前
华为eNSP:mux-vlan
网络·安全·华为
昔我往昔11 小时前
阿里云文本内容安全处理
安全·阿里云·云计算
棱角~~13 小时前
盘点和嗨格式一样好用的10款数据恢复!!
数据库·经验分享·安全·电脑·学习方法
NETFARMER运营坛14 小时前
如何优化 B2B 转化率?这些步骤你不可不知
大数据·安全·阿里云·ai·ai写作
安徽京准14 小时前
京准时钟:无人机卫星信号安全防护隔离装置
安全·无人机·信号安全防护装置·卫星安全隔离装置·北斗授时安全隔离·北斗对时防护隔离装置