一文搞懂RSA非对称加密(1)--如何生成秘钥对

403 阅读3分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第1天,点击查看活动详情 >>

RSA算法简介

加密和解密使用相同的密钥叫对称加密方式,而非对称加密算法(公钥加密方式)RSA加密与解密分别用不同的密钥,公钥用于加密,私钥用于解密。

比如发送者S要给接受者R传输报文信息,为了避免信息泄露,秘钥签发者R事先通过RSA加密算法生成秘钥对,并且将公钥事先给到S,私钥则自己保留,S向R传输信息时,先用R提供的公钥加密报文,然后再将报文传输给R,R获取加密后的信息,再通过其单独持有的私钥解密报文,即使报文被窃听,窃听者没有私钥,也无法解密。公钥对外公开的,私钥自己保留,由于公钥是公开的,任何人都能拿到(会同时给到多个人),都可以使用公钥来加密发送伪造内容,因此,验证发送者的身份,确保报文的安全性显得非常重要。

考虑到一种情况:发送者S获取接收者R的公钥时,被中间人A获取到了这个公钥,通过公钥对信息加密,冒充S来给R发篡改的报文,同样R接受信息后也能够通过持有的私钥解密报文数据,接受者无法辨别数据发送者身份,存在报文非法修改风险,为了区分发送者的身份,那么这个时候我们就要用到签名。

签名原理:对报文做摘要,能防止被篡改。发送方对报文原文做加盐hash摘要,把加密原文和摘要一起发送给接收方,接收方解密后,用同样的hash方法计算并比对摘要,就能判断原文是否被篡改。

签名过程:发送者S同样也生成了一对秘钥,事先将公钥给到R,在发送消息之前,先用R给的公钥对报文加密,然后签名使用S自己私钥来签名,最后将加密的消息和签名一起发过去给R,接受者R在接收到发送者S发送的数据后,首先使用S的公钥对签名信息进行验签,确认身份信息,如果确认是发送者S,然后再R才利用私钥对加密消息进行解密,从而隔离非法数据包的接收。

这样一来,发送过程信息被获取,没有R的私钥无法解密信息,即使获取到发送者S的公钥,想要仿造发送信息没有S的私钥无法签名,同理R给S回复信息时,可以通过R的公钥加密,自己的私钥生成签名,S接收到数据使用同样的方式进行解密验证身份。私钥加签,公钥验签,这样就能确保只有私钥持有者也就是发送者能合法发送数据。

总结: 公钥加密并验签 私钥解密并签名

生产秘钥对(复制粘贴可用)

/**
 * RSA密钥对对象
 */
public static class RSAKeyPair {

    private String publicKey;
    private String privateKey;

    public RSAKeyPair(String publicKey, String privateKey) {
        this.publicKey = publicKey;
        this.privateKey = privateKey;
    }

    public String getPublicKey() {
        return publicKey;
    }

    public String getPrivateKey() {
        return privateKey;
    }

}
public static final String ALGORITHM_FOR_KEY_FACTORY = "RSA";
/**
 * 构建RSA密钥对
 *
 * @return
 * @throws NoSuchAlgorithmException
 */
public static RSAKeyPair generateKeyPair() throws NoSuchAlgorithmException, NoSuchProviderException {
    KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(QuickPaymentConstant.ALGORITHM_FOR_KEY_FACTORY);
    keyPairGenerator.initialize(1024);
    KeyPair keyPair = keyPairGenerator.generateKeyPair();
    RSAPublicKey rsaPublicKey = (RSAPublicKey) keyPair.getPublic();
    RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) keyPair.getPrivate();
    String publicKeyString = Base64.getEncoder().encodeToString(rsaPublicKey.getEncoded());
    String privateKeyString = Base64.getEncoder().encodeToString(rsaPrivateKey.getEncoded());
    RSAKeyPair rsaKeyPair = new RSAKeyPair(publicKeyString, privateKeyString);
    return rsaKeyPair;
}
public static void main(String[] args) throws Exception {
    System.out.println("\n");
    RsaUtil.RSAKeyPair keyPair = generateKeyPair();
    System.out.println("公钥:" + keyPair.getPublicKey());
    System.out.println("私钥:" + keyPair.getPrivateKey());
}

有任何问题欢迎留言