RSA加解密算法、签名详解和RSA java工具类

前言

RSA算法是很常用的一种非对称的加解密算法和签名算法,这篇文章主要对这种算法做一个详解,并提供一个实现比较好的Java工具类供大家使用。

算法的思想

在这里插入图片描述

  1. RSA是一个非对称加密算法,它通常是先生成一对RSA 密钥,其中之一是保密密钥,由用户保存;另一个为公开密钥,可对外公开。
    • 公开密钥加密(public-key cryptography),也称为非对称加密(asymmetric cryptography),一种密码学算法类型,在这种密码学方法中,需要一对密钥,一个是私人密钥,另一个则是公开密钥。这两个密钥是数学相关,用某用户密钥加密后所得的信息,只能用该用户的解密密钥才能解密。如果知道了其中一个,并不能计算出另外一个。因此如果公开了一对密钥中的一个,并不会危害到另外一个的秘密性质。称公开的密钥为公钥;不公开的密钥为私钥。
    • 公钥加密,私钥解密。公钥可以发给所有人,数据加密之后用获得方可以用私钥解密,以此来得到真实的数据。设两个用户A向B发送信息,B的公钥为c,对应私钥(也是属于B的)为d,明文为x。A用公钥对明文进行加密形成密文c(x),然后传输密文;B收到密文,用私钥对密文进行解密d(c(x)),得到要通信的明文x。B向A发送信息反之。
    • 私钥加密,公钥解密,用于客户验证持有私钥一方发布的数据或文件是完整准确的,接收者由此可知这条信息确实来自于拥有私钥的某人,这被称作数字签名,公钥的形式就是数字证书。例如,从网上下载的安装程序,一般都带有程序制作者的数字签名,可以证明该程序的确是该作者(公司)发布的而不是第三方伪造的且未被篡改过(身份认证/验证)。公钥的形式就是数字证书。简单的说就是,我自己用私钥加密了,生成的就是数字签名。而我把公钥开放作为数字证书,别人就可以那我的数字证书来核对数字签名是不是我的。
      在这里插入图片描述
    • 常见的公钥加密算法有: [2] RSA、ElGamal、背包算法、Rabin(RSA的特例)、迪菲-赫尔曼密钥交换协议中的公钥加密算法、椭圆曲线加密算法(Elliptic Curve Cryptography, ECC)。使用最广泛的是RSA算法(由发明者Rivest、Shmir和Adleman姓氏首字母缩写而来)是著名的公开金钥加密算法,ElGamal是另一种常用的非对称加密算法。
  2. 为提高保密强度,RSA密钥至少为500位长,一般推荐使用1024位。
    • RSA 算法密钥长度的选择是安全性和程序性能平衡的结果,密钥长度越长,安全性越好,加密解密所需时间越长。
    • 密钥长度增长一倍,公钥操作所需时间增加约 4 倍,私钥操作所需时间增加约 8 倍,公私钥生成时间约增长 16 倍;
    • 一次能加密的明文长度与密钥长度成正比:
      len_in_byte(raw_data) = len_in_bit(key)/8 -11,如 1024bit 的密钥,一次能加密的内容长度为 1024/8 -11 = 117 byte
      所以非对称加密一般都用于加密对称加密算法的密钥,而不是直接加密内容。
    • 加密后密文的长度为密钥的长度,如密钥长度为 1024b(128Byte),最后生成的密文固定为 1024b(128Byte)
      密文长度就是给定符合条件的明文加密出来的结果位长,这个可以确定,加密后的密文位长跟密钥的位长度是相同的,因为加密公式:
      C=(P^e)%n
      所以,C 最大值就是 n-1,所以不可能超过 n 的位数。
      尽管可能小于 n 的位数,但从传输和存储角度,仍然是按照标准位长来进行的。
      因此,即使我们加密一字节的明文,运算出来的结果也要按照标准位长来使用。
  3. RSA算法是第一个能同时用于加密和数字签名的算法。

RSA加密、签名区别

加密和签名都是为了安全性考虑,但略有不同。常有人问加密和签名是用私钥还是公钥?其实都是对加密和签名的作用有所混淆。简单的说,加密是为了防止信息被泄露,而签名是为了防止信息被篡改。这里举2个例子说明。

第一个场景:战场上,B要给A传递一条消息,内容为某一指令。

RSA的加密过程如下:

(1)A生成一对密钥(公钥和私钥),私钥不公开,A自己保留。公钥为公开的,任何人可以获取。

(2)A传递自己的公钥给B,B用A的公钥对消息进行加密。

(3)A接收到B加密的消息,利用A自己的私钥对消息进行解密。

在这个过程中,只有2次传递过程,第一次是A传递公钥给B,第二次是B传递加密消息给A,即使都被敌方截获,也没有危险性,因为只有A的私钥才能对消息进行解密,防止了消息内容的泄露

第二个场景:A收到B发的消息后,需要进行回复“收到”。

RSA签名的过程如下:

(1)A生成一对密钥(公钥和私钥),私钥不公开,A自己保留。公钥为公开的,任何人可以获取。

(2)A用自己的私钥对消息加签,形成签名,并将加签的消息和消息本身一起传递给B。

(3)B收到消息后,在获取A的公钥进行验签,如果验签出来的内容与消息本身一致,证明消息是A回复的。

在这个过程中,只有2次传递过程,第一次是A传递加签的消息和消息本身给B,第二次是B获取A的公钥,即使都被敌方截获,也没有危险性,因为只有A的私钥才能对消息进行签名,即使知道了消息内容,也无法伪造带签名的回复给B,防止了消息内容的篡改

但是,综合两个场景你会发现,第一个场景虽然被截获的消息没有泄露,但是可以利用截获的公钥,将假指令进行加密,然后传递给A。第二个场景虽然截获的消息不能被篡改,但是消息的内容可以利用公钥验签来获得,并不能防止泄露。所以在实际应用中,要根据情况使用,也可以同时使用加密和签名,比如A和B都有一套自己的公钥和私钥,当A要给B发送消息时,先用B的公钥对消息加密,再对加密的消息使用A的私钥加签名,达到既不泄露也不被篡改,更能保证消息的安全性。

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

非对称加密和对称加密和哈希加密

对称加密

对称加密指的就是加密和解密使用同一个秘钥,所以叫做对称加密。对称加密只有一个秘钥,作为私钥。

具体算法有:DES,3DES,TDEA,Blowfish,RC5,IDEA。常见的有:DES,AES,3DES等等。

优点:算法公开、计算量小、加密速度快、加密效率高。适合加密大量数据、明文长度和密文相同
缺点:秘钥的管理和分发非常困难,不够安全。在数据传送前,发送方和接收方必须商定好秘钥,然后双方都必须要保存好秘钥,如果一方的秘钥被泄露,那么加密信息也就不安全了。另外,每对用户每次使用对称加密算法时,都需要使用其他人不知道的唯一秘钥,这会使得收、发双方所拥有的钥匙数量巨大,密钥管理成为双方的负担。

非对称加密

非对称加密指的是:加密和解密使用不同的秘钥,一把作为公开的公钥,另一把作为私钥。公钥加密的信息,只有私钥才能解密。私钥加密的信息,只有公钥才能解密。 私钥只能由一方安全保管,不能外泄,而公钥则可以发给任何请求它的人。非对称加密使用这对密钥中的一个进行加密,而解密则需要另一个密钥。

我们常见的数字证书、加密狗即是采用非对称加密来完成安全验证的。

优点:安全性更高,公钥是公开的,秘钥是自己保存的,不需要将私钥给别人。 提供了对称密码技术无法或很难提供的服务(数字签名)。
缺点:加密和解密花费时间长、速度慢,只适合对少量数据进行加密。

主要算法:RSA、Elgamal、背包算法、Rabin、HD,ECC(椭圆曲线加密算法)。常见的有:RSA,ECC

哈希加密

哈希(Hash),一般翻译做"散列",也有直接音译为"哈希"的,就是把任意长度的输入(又叫做预映射, pre-image),通过散列算法,变换成固定长度的输出,该输出通常称作散列值、数字指纹 或 消息摘要。这种转换是一种压缩映射,也就是,散列值的空间通常远小于输入的空间(不同的输入有可能会散列成相同的输出,几率非常小),而不可能从散列值来逆向推出输入值,也就是说,哈希函数是不可逆的。简单的说就是一种将任意长度的消息压缩到某一固定长度的消息摘要的函数。
哈希函数也称为散列函数、杂凑函数等。
哈希函数的特点:不可逆性,碰撞约束
目前网上大部分的哈希破解都是利用哈希值的密码字典进行爆破。

常见的哈希算法有:MD4 、MD5 、 SHA1、 SHA224 、 SHA256 、 SHA384 、SHA 512
哈希算法的用途:文件校验、数字签名、安全传输和存储口令

区别

对称加密算法相比非对称加密算法来说,加解密的效率要高得多。但是缺陷在于对于秘钥的管理上,以及在非安全信道中通讯时,密钥交换的安全性不能保障。所以在实际的网络环境中,会将两者混合使用.

例如针对C/S模型,

服务端计算出一对秘钥pub/pri。将私钥保密,将公钥公开。

客户端请求服务端时,拿到服务端的公钥pub。

客户端通过AES计算出一个对称加密的秘钥X。 然后使用pub将X进行加密。

客户端将加密后的密文发送给服务端。服务端通过pri解密获得X。

然后两边的通讯内容就通过对称密钥X以对称加密算法来加解密。

Java rsa工具类

包含以下功能:

  1. 生成公、私密钥
  2. 公、私密钥加密
  3. 公、私密钥解密
  4. 签名、验签
考虑到安全,请使用时把默认的公私钥替换成你生成的!
package cn.hengyumo.humor.utils;

import javax.crypto.Cipher;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;

/**
 * RsaUtil
 * RSA加密工具类
 *
 * @author hengyumo
 * @since 2019/11/11
 * @version 1.0
 */
@SuppressWarnings({"WeakerAccess", "unused"})
public class RsaUtil {

    /**
     * 缺省的1024位密钥对,可处理117个字节的数据
     */
    private static final String PUBLIC_KEY = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC3nL3e0ESJSALcXfS3uazX3z/VcepVDpjK/9D90PSYhvm2PIiOmchmxbXLTmg+PwikNMZTU/9OKrkVwBI13tF4ku1Lim6AnvalkDjOcbRfbcyuto8j0gAEYoKbnDAlxAK0tqGg7Q9Vt6Dobn/bjlfP52KDTbnKaUkf4dN4heoQcQIDAQAB";

    private static final String PRIVATE_KEY = "MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBALecvd7QRIlIAtxd9Le5rNffP9Vx6lUOmMr/0P3Q9JiG+bY8iI6ZyGbFtctOaD4/CKQ0xlNT/04quRXAEjXe0XiS7UuKboCe9qWQOM5xtF9tzK62jyPSAARigpucMCXEArS2oaDtD1W3oOhuf9uOV8/nYoNNucppSR/h03iF6hBxAgMBAAECgYAuYabI4R1e/FTUq9tEid+yjE+IsIT8RXqtVN/LLfyLhxUPRs1MEGbCJ1Fb8Qt+Jdgd+sLai85jRYGJkAJJn2aUPCRfLTZJl4KD5R4K2l6Xb5npgfBnoE1RYBd6sb2pwKHSFTeXx516pAAhaTjorF+nGzl9qig1xarRQunaKY0kwQJBANyJc/2Zx1V/3qzpXgCYM1fjCN6AXBh75FXBM7EFz+fU1RSi4Pzpbo3aLilobLG3MaKjrGYs2s9+3Z7KjXJFxjkCQQDVI0LT3RPAkCGGm2Gm+nbtLRkwdus32snJmWuca05LNuihzJIF/n9tB/JdzCRyU1bUHWK7W4Pt9v8DyXRXRlv5AkEAubmoTTJshLyjMst1ttp2otU4aul+pb/wk6eZeMOES6EZsb9Z6qRLznqn1YdzwladHnLohUPRIl2dFlVOuaW5QQJBAKg6fLTc+oozOUMVwa4aY2QxBIDMXDxp5HvLLLT5vYKAhH2xClDQ36Mfcp22U84pGY+y4gsf4LIjEoXarIl2b4ECQHU9JR6EZVmCQHKfHPOPauqRkRv81tXsWJSomJF1OfixUvRBDeDj/skme7tB1XxJGOLJGACSXDvqVvcAbRXN9oQ=";

    /**
     * 算法
     */
    public static final String RSA_ALGORITHM = "RSA/ECB/PKCS1Padding";
    public static final String RSA_ALGORITHM_NO_PADDING = "RSA";

    /**
     * 默认的密钥长度
     */
    private static final Integer KEY_LENGTH = 1024;

    /**
     * 字符集
     */
    private static final String CHARSET = "utf-8";

    /**
     * 签名算法
     */
    private static final String SIGNATURE_INSTANCE = "SHA1WithRSA";



    /**
     * 获取默认公钥
     *
     * @return 默认公钥实例
     * @throws Exception e
     */
    public PublicKey getDefaultPublicKey() throws Exception {
        return getPublicKey(PUBLIC_KEY);
    }

    /**
     * 获取默认私钥
     *
     * @return 默认私钥实例
     * @throws Exception e
     */
    public PrivateKey getDefaultPrivateKey() throws Exception {
        return getPrivateKey(PRIVATE_KEY);
    }

    /**
     * 生成密钥对
     *
     * @param keyLength 密钥长度
     *
     * @return 密钥对
     * @throws Exception e
     */
    public static KeyPair getKeyPair(int keyLength) throws Exception {
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(RSA_ALGORITHM_NO_PADDING);
        keyPairGenerator.initialize(keyLength);
        return keyPairGenerator.generateKeyPair();
    }

    /**
     * 生成默认长度的密钥对
     *
     * @return 密钥对
     * @throws Exception e
     */
    public static KeyPair getKeyPair() throws Exception {
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(RSA_ALGORITHM_NO_PADDING);
        keyPairGenerator.initialize(KEY_LENGTH);
        return keyPairGenerator.generateKeyPair();
    }

    /**
     * 公钥字符串转PublicKey实例
     *
     * @param publicKey 公钥字符串
     *
     * @return PublicKey实例
     * @throws Exception e
     */
    public static PublicKey getPublicKey(String publicKey) throws Exception {
        // java8 的Base64.getDecoder()编码规范和java7不同,也和jsencrypt不兼容,因此要用Base64.getMimeDecoder()
        byte[] publicKeyBytes = Base64.getMimeDecoder().decode(publicKey.getBytes());
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKeyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance(RSA_ALGORITHM_NO_PADDING);
        return keyFactory.generatePublic(keySpec);
    }

    /**
     * 私钥字符串转PrivateKey实例
     *
     * @param privateKey 私钥字符串
     *
     * @return PrivateKey实例
     * @throws Exception e
     */
    public static PrivateKey getPrivateKey(String privateKey) throws Exception {
        byte[] privateKeyBytes = Base64.getMimeDecoder().decode(privateKey.getBytes());
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKeyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance(RSA_ALGORITHM_NO_PADDING);
        return keyFactory.generatePrivate(keySpec);
    }

    /**
     * 公钥加密
     *
     * @param content 明文
     * @param publicKey 公钥
     *
     * @return 密文
     * @throws Exception e
     */
    public static byte[] encryptByPublicKey(byte[] content, PublicKey publicKey) throws Exception {
        Cipher cipher = Cipher.getInstance(RSA_ALGORITHM);
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);
        return cipher.doFinal(content);
    }

    /**
     * 公钥加密
     *
     * @param content 明文
     * @param publicKey 公钥字符串
     *
     * @return 密文
     * @throws Exception e
     */
    public static String encryptByPublicKey(String content, String publicKey) throws Exception {
        return new String(Base64.getMimeEncoder().encode(
                encryptByPublicKey(content.getBytes(CHARSET), getPublicKey(publicKey))));

    }

    /**
     * 使用默认公钥加密-字节
     *
     * @param content 明文字节数组
     *
     * @return 密文字节数组
     * @throws Exception e
     */
    public static byte[] encryptByPublicKey(byte[] content) throws Exception {
        return encryptByPublicKey(content, getPublicKey(PUBLIC_KEY));
    }

    /**
     * 使用默认公钥加密-字符串
     *
     * @param content 明文字符串
     *
     * @return 密文字符串
     * @throws Exception e
     */
    public static String encryptByPublicKey(String content) throws Exception {
        return new String(Base64.getMimeEncoder().encode(encryptByPublicKey(content.getBytes(CHARSET))));
    }

    /**
     * 私钥解密
     *
     * @param content 密文
     * @param privateKey 私钥
     *
     * @return 解密后的明文
     * @throws Exception e
     */
    public static byte[] decryptByPrivateKey(byte[] content, PrivateKey privateKey) throws Exception {
        Cipher cipher = Cipher.getInstance(RSA_ALGORITHM);
        cipher.init(Cipher.DECRYPT_MODE, privateKey);
        return cipher.doFinal(content);
    }

    /**
     * 使用私钥字符串解密
     *
     * @param content 密文
     * @param privateKey 私钥字符串
     *
     * @return 明文
     * @throws Exception e
     */
    public static String decryptByPrivateKey(String content, String privateKey) throws Exception {
        return new String(decryptByPrivateKey(
                Base64.getMimeDecoder().decode(content), getPrivateKey(privateKey)), CHARSET);

    }

    /**
     * 使用默认私钥解密-字节
     *
     * @param content 密文字节数组
     *
     * @return 明文字节数组
     * @throws Exception e
     */
    public static byte[] decryptByPrivateKey(byte[] content) throws Exception {
        return decryptByPrivateKey(content, getPrivateKey(PRIVATE_KEY));
    }

    /**
     * 使用默认私钥解密-字符串
     *
     * @param content 密文
     *
     * @return 明文
     * @throws Exception e
     */
    public static String decryptByPrivateKey(String content) throws Exception {
        return new String(decryptByPrivateKey(Base64.getMimeDecoder().decode(content)), CHARSET);
    }

    /**
     * 私钥加密
     *
     * @param content 明文
     * @param privateKey 私钥
     *
     * @return 密文
     * @throws Exception e
     */
    public static byte[] encryptByPrivateKey(byte[] content, PrivateKey privateKey) throws Exception {
        Cipher cipher = Cipher.getInstance(RSA_ALGORITHM);
        cipher.init(Cipher.ENCRYPT_MODE, privateKey);
        return cipher.doFinal(content);
    }

    /**
     * 私钥加密
     *
     * @param content 明文
     * @param privateKey 私钥字符串
     *
     * @return 密文
     * @throws Exception e
     */
    public static String encryptByPrivateKey(String content, String privateKey) throws Exception {
        return new String(Base64.getMimeEncoder().encode(
                encryptByPrivateKey(content.getBytes(CHARSET), getPrivateKey(privateKey))), CHARSET);
    }

    /**
     * 使用默认私钥加密-字节
     *
     * @param content 明文字节数组
     * @return 密文字节数组
     *
     * @throws Exception e
     */
    public static byte[] encryptByPrivateKey(byte[] content) throws Exception {
        return encryptByPrivateKey(content, getPrivateKey(PRIVATE_KEY));
    }

    /**
     * 使用默认私钥加密-字符串
     *
     * @param content 明文字符串
     * @return 密文字符串
     *
     * @throws Exception e
     */
    public static String encryptByPrivateKey(String content) throws Exception {
        return new String(Base64.getMimeEncoder().encode(
                encryptByPrivateKey(content.getBytes(CHARSET))), CHARSET);
    }

    /**
     * 公钥解密
     *
     * @param content 密文
     * @param publicKey 公钥
     *
     * @return 明文
     * @throws Exception e
     */
    public static byte[] decryptByPublicKey(byte[] content, PublicKey publicKey) throws Exception {
        Cipher cipher = Cipher.getInstance(RSA_ALGORITHM);
        cipher.init(Cipher.DECRYPT_MODE, publicKey);
        return cipher.doFinal(content);
    }

    /**
     * 公钥解密
     *
     * @param content 密文
     * @param publicKey 公钥字符串
     *
     * @return 明文
     * @throws Exception e
     */
    public static String decryptByPublicKey(String content, String publicKey) throws Exception {
        return new String(decryptByPublicKey(
                Base64.getMimeDecoder().decode(content), getPublicKey(publicKey)), CHARSET);

    }

    /**
     * 使用默认私钥解密-字节
     *
     * @param content 密文字节数组
     *
     * @return 明文字节数组
     * @throws Exception e
     */
    public static byte[] decryptByPublicKey(byte[] content) throws Exception {
        return decryptByPublicKey(content, getPublicKey(PUBLIC_KEY));
    }

    /**
     * 使用默认私钥解密-字符串
     *
     * @param content 密文字符串
     *
     * @return 明文字符串
     * @throws Exception e
     */
    public static String decryptByPublicKey(String content) throws Exception {
        return new String(decryptByPublicKey(Base64.getMimeDecoder().decode(content)), CHARSET);
    }

    /**
     * 签名
     *
     * @param content 明文
     * @param privateKey 私钥
     *
     * @return 签名后的密文
     * @throws Exception e
     */
    public static byte[] sign(byte[] content, PrivateKey privateKey) throws Exception {
        Signature signature = Signature.getInstance(SIGNATURE_INSTANCE);
        signature.initSign(privateKey);
        signature.update(content);
        return signature.sign();
    }

    /**
     * 签名
     *
     * @param content 明文
     * @param privateKey 密钥字符串
     *
     * @return 签名后的密文
     * @throws Exception e
     */
    public static String sign(String content, String privateKey) throws Exception {
        return new String(Base64.getMimeEncoder().encode(
                sign(content.getBytes(CHARSET), getPrivateKey(privateKey))), CHARSET);
    }

    /**
     * 使用默认私钥签名
     *
     * @param content 明文
     *
     * @return 签名后的密文
     * @throws Exception e
     */
    public static byte[] sign(byte[] content) throws Exception {
        return sign(content, getPrivateKey(PRIVATE_KEY));
    }

    /**
     * 使用默认私钥签名
     *
     * @param content 明文
     *
     * @return 签名后的密文
     * @throws Exception e
     */
    public static String sign(String content) throws Exception {
        return new String(Base64.getMimeEncoder().encode(
                sign(content.getBytes(CHARSET))), CHARSET);
    }

    /**
     * 验签
     *
     * @param content 明文
     * @param sign 签名
     * @param publicKey 公钥
     *
     * @return true or false
     * @throws Exception e
     */
    public static boolean verify(byte[] content, byte[] sign,  PublicKey publicKey) throws Exception {
        Signature signature = Signature.getInstance(SIGNATURE_INSTANCE);
        signature.initVerify(publicKey);
        signature.update(content);
        return signature.verify(sign);
    }

    /**
     * 验签
     *
     * @param content 明文
     * @param sign 签名
     * @param publicKey 公钥字符串
     *
     * @return true or false
     * @throws Exception e
     */
    public static boolean verify(String content, String sign, String publicKey) throws Exception {
        return verify(content.getBytes(CHARSET),
                Base64.getMimeDecoder().decode(sign), getPublicKey(publicKey));
    }

    /**
     * 使用默认公钥验签
     *
     * @param content 明文
     * @param sign 签名
     *
     * @return true or false
     * @throws Exception e
     */
    public static boolean verify(byte[] content, byte[] sign) throws Exception {
        return verify(content, sign, getPublicKey(PUBLIC_KEY));
    }

    /**
     * 使用默认公钥验签
     *
     * @param content 明文
     * @param sign 签名
     *
     * @return true or false
     * @throws Exception e
     */
    public static boolean verify(String content, String sign) throws Exception {
        return verify(content.getBytes(CHARSET),
                Base64.getMimeDecoder().decode(sign), getPublicKey(PUBLIC_KEY));
    }

    /**
     * 测试
     *
     * @param args args
     */
    public static void main(String[] args) {
        try {
            // 生成公私密钥
            KeyPair keyPair = RsaUtil.getKeyPair(1024);
            PublicKey publicKey = keyPair.getPublic();
            PrivateKey privateKey = keyPair.getPrivate();

            // 获取密钥字符串
            String pkStr = new String(Base64.getMimeEncoder().encode(publicKey.getEncoded()));
            String skStr = new String(Base64.getMimeEncoder().encode(privateKey.getEncoded()));

            // 公钥
            System.out.println(pkStr);
            System.out.println('\n');
            // 私钥
            System.out.println(skStr);
            System.out.println('\n');

            // 明文
            String p = "A-B-C-D-E-F-G-1234567";

            // 公钥加密
            String s = RsaUtil.encryptByPublicKey(p, pkStr);
            System.out.println(s);
            System.out.println('\n');

            // 私钥解密
            String sp = RsaUtil.decryptByPrivateKey(s, skStr);
            System.out.println(sp);
            System.out.println('\n');

            // 签名
            String name = "hengyumo12345";

            String nameSign = RsaUtil.sign(name);

            // 验签
            System.out.println(RsaUtil.verify(name, nameSign));
        }
        catch (Exception e) {
            e.printStackTrace();
        }
    }
}

应用探讨

数字信封
混合加密实现方式:

  1. 信息(明文)采用DES密钥加密得到密文。
  2. 使用RSA加密前面的DES密钥信息得到key,最终将密文和key进行传递。

接收到信息后解密:

  1. 用RSA解密key得到DES密钥。
  2. 再用DES秘钥解密文信息,最终就可以得到我们要的信息(明文)。

在这里插入图片描述

参考&引用

RSA
https://baike.baidu.com/item/RSA%E7%AE%97%E6%B3%95/263310?fr=aladdin
非对称加密
https://baike.baidu.com/item/%E5%85%AC%E5%BC%80%E5%AF%86%E9%92%A5%E5%8A%A0%E5%AF%86
数字签名
https://baike.baidu.com/item/%E6%95%B0%E5%AD%97%E7%AD%BE%E5%90%8D/212550?fr=aladdin
RSA详解
https://www.cnblogs.com/NathanYang/p/9182929.html
【IoT】加密与安全:非对称加密算法 RSA 1024 公钥、秘钥、明文和密文长度
https://blog.csdn.net/liwei16611/article/details/83751851
RSA加密、解密、签名、验签的原理及方法
https://www.cnblogs.com/pcheng/p/9629621.html
RSA加密工具类(Java)
https://blog.csdn.net/yimcarson/article/details/84071973
非对称加密的优缺点
https://blog.csdn.net/u011078141/article/details/94285175
密码学(对称与非对称加密 哈希算法)
https://www.cnblogs.com/csnd/p/11807787.html
加盐密码哈希:如何正确使用 (密码加密的经典文章)
https://crackstation.net/hashing-security.htm
http://blog.jobbole.com/61872/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值