天天看点

Java 实现RSA非对称加密算法的签名与验签

1.RAS简介

RSA加密是非对称加密,由一对秘钥进行完成加密解密,分别称为公钥和私钥,公钥加密,私钥解密,RSA可以完成加密和签名;

2.加密与签名的区别

加密是为了防止信息被泄露,签名是为了防止信息被篡改;

3.RSA加密过程

假如B要发消息给A,首先A在本地生产一对秘钥,公钥和私钥,并将公钥发送给B,B使用公钥对消息进行加密,然后传输给A,A接收到消息后在本地使用私钥解密;

缺点:这种加密过程保证了消息不被泄露,但是避免不了消息被篡改,假如B发送给A的消息被黑客劫持,他通过公钥,自己伪造一条消息,通过公钥加密,发送给A,这样A收到的消息就不是B发送给A的了;

4.RSA签名过程

A发送消息给B的时候,用私钥对消息进行加签,将加签后的消息与消息本体发给B,B使用公钥进行验签,如果验签出来的内容和消息本身一致,证明消息才是A回复的;

这样也会有一个问题,当黑客获取到消息后,可以使用公钥验签,来查看消息,并不能防止消息泄露;

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

5.RSA签名/验签实例

@Test
void contextLoads() throws Exception {

    /**
     * 1、生成一对RSA密钥。
     * */
    // 随机生成一对 RAS 密钥(包含公钥和私钥)
    KeyPair keyPair = generateKeyPair();
    // 获取 公钥 和 私钥
    PublicKey publicKey = keyPair.getPublic();
    PrivateKey privateKey = keyPair.getPrivate();

    /**
     * 2.生成原始数据
     * */
    //原始数据 JSON字符串
    String data =  "{" +
            "\"notifyTime\": \"20210519155300\", " +
            "\"notifyType\": \"TEST\", " +
            "\"version\": \"1.0.0TEST\"" +
            "}";

    /**
     * 3.私钥签名:对数据进行签名,计算签名结果。
     * */
    // 根据指定算法获取签名工具
    Signature sign = Signature.getInstance("Sha1WithRSA");
    // 用私钥初始化签名工具
    sign.initSign(privateKey);
    // 添加要签名的数据
    sign.update(data.getBytes());
    //计算签名结果(签名信息)
    byte[] signInfo = sign.sign();
    // 输出签名结果的 Base64 字符串
    System.out.println(new BASE64Encoder().encode(signInfo));

    /**
     * 4.公钥验签:用公钥校验数据是否被改变
     * */
    // 根据指定算法获取签名工具
    sign = Signature.getInstance("Sha1WithRSA");
    // 用公钥初始化签名工具
    sign.initVerify(publicKey);
    // 添加要校验的数据
    sign.update(data.getBytes());
    // 校验数据的签名信息是否正确,
    // 如果返回 true, 说明该数据的签名信息来自该公钥对应的私钥,
    // 同一个私钥的签名, 数据和签名信息一一对应, 只要其中有一点修改, 则用公钥无法校验通过,
    // 因此可以用私钥签名, 然后用公钥来校验数据的完整性与签名者(所有者)
    boolean verify = sign.verify(signInfo);
    System.out.println(verify);

    /**
     * 测试数据被修改后的验签是否还有效
     * */
    data =  "{" +
            "\"notifyTime\": \"20210519155300\", " +
            "\"notifyType\": \"TEST11\", " +
            "\"version\": \"1.0.0TESTTTT\"" +
            "}";
    sign = Signature.getInstance("Sha1WithRSA");
    sign.initVerify(publicKey);
    sign.update(data.getBytes());
    verify = sign.verify(signInfo);
    System.out.println(verify);
}


/**
 * 随机生成 RSA 密钥对(包含公钥和私钥)
 */
private static KeyPair generateKeyPair() throws Exception {
    // 获取指定算法的密钥对生成器
    KeyPairGenerator gen = KeyPairGenerator.getInstance("RSA");
    // 初始化密钥对生成器(指定密钥长度, 使用默认的安全随机数源)
    gen.initialize(2048);
    // 随机生成一对密钥(包含公钥和私钥)
    return gen.generateKeyPair();
}
           

过程中如果有小伙伴遇到问题或者有好的见解可以及时联系