zoukankan      html  css  js  c++  java
  • 廖雪峰Java10加密与安全-5签名算法-1RSA签名算法

    1.数字签名

    甲在发送加密消息的时候,还要发送自己的签名,而这个签名是用甲的privateKey计算的;而乙要验证这个签名是否是合法的,会用甲的publicKey去验证,如果验证成功,这个消息确实是甲发送的。

    数字签名:

    • 发送方用自己的私钥对消息进行签名:sig = signature(privateKey, "message")
    • 接收方用发送方的公钥验证签名是否有效:boolean vaild = verify(publicKey, sig,"message")。如果publicKey,sig,message任何一个发生改变,签名都是无效的。
    • 数字签名≈混入了私钥/公钥的摘要

    数字签名的目的:

    • 确认信息是某个发送方发送的。只有发送方用自己的privateKey签名,其他人才能用发送方的publicKey验证签名。
    • 发送方不能抵赖他发送了消息。因为用谁的publicKey成功验证的签名,就说明一定是他用自己的privateKey签名的。所以privateKey相当于用户的身份。
    • 数据在传输过程中没有被修改

    常用数字签名方法:

    • MD5withRSA
    • SHA1withRSA
    • SHA256withRSA

    2代码示例

    package com.testList;
    
    import java.security.*;
    import java.security.spec.PKCS8EncodedKeySpec;
    import java.security.spec.X509EncodedKeySpec;
    import java.util.Arrays;
    import java.util.Base64;
    
    public class SecRSASignature {
        PrivateKey sk;//定义私钥
        PublicKey pk;//定义公钥
        //构造方法1:获取公钥/私钥对
        public SecRSASignature() throws GeneralSecurityException{
            KeyPairGenerator kpGen = KeyPairGenerator.getInstance("RSA");//使用RSA
            kpGen.initialize(1024);//初始化为1024字节
            KeyPair kp = kpGen.generateKeyPair();//生成公钥、私钥
            this.sk = kp.getPrivate();
            this.pk = kp.getPublic();
        }
        //构造方法2:从保存的字节中提取公钥/私钥
        public SecRSASignature(byte[] pk,byte[] sk) throws GeneralSecurityException{
            KeyFactory kf = KeyFactory.getInstance("RSA");
            X509EncodedKeySpec pkSpec = new X509EncodedKeySpec(pk);
            this.pk = kf.generatePublic(pkSpec);
            PKCS8EncodedKeySpec skSpec = new PKCS8EncodedKeySpec(sk);
            this.sk = kf.generatePrivate(skSpec);
        }
        //返回私钥的byte数组
        public byte[] getPrivateKey(){
            return this.sk.getEncoded();
        }
        //返回公钥的byte数组
        public byte[] getPublicKey(){
            return this.pk.getEncoded();
        }
        //获取签名
        public byte[] sign(byte[] message) throws GeneralSecurityException{
            Signature signature = Signature.getInstance("SHA1withRSA");
            signature.initSign(this.sk);
            signature.update(message);
            return signature.sign();
        }
        //传入message,使用公钥与签名sign进行校验
        public boolean verify(byte[] message,byte[] sign) throws GeneralSecurityException{
            Signature signature = Signature.getInstance("SHA1withRSA");
            signature.initVerify(this.pk);
            signature.update(message);
            return signature.verify(sign);
        }
        public static void main(String[] args) throws Exception{
            byte[] message = "Hello,使用SHA1withRSA算法进行数字签名".getBytes("utf-8");
    
            SecRSASignature rsas = new SecRSASignature();
            byte[] sign = rsas.sign(message);
            System.out.println("sign:"+ Base64.getEncoder().encodeToString(sign));
    
            //使用原有的message、sign进行校验
            boolean verified1 = rsas.verify(message,sign);
            System.out.println("verify:"+verified1);
            //创建新的SecRSASiginature对象,使用原有的sign与新对象进行校验
            boolean verified2 = new SecRSASignature().verify(message,sign);
            System.out.println("verfied with another public key:"+verified2);
            //修改message信息
            message[0]=100;
            boolean verifed3 = rsas.verify(message,sign);
            System.out.println("verified with changed message: "+verifed3);
        }
    }
    

    3.总结:

    • 数字签名就是发送方的私钥对原始数据进行签名
    • 只有用发送方公钥才能通过签名验证
      * 防止伪造发送方
      * 防止抵赖发送过信息
      * 防止信息在传输过程中被修改
    • 常用算法:MD5withRSA/SHA1withRSA/SHA256widthRSA
  • 相关阅读:
    ssm 在不同的数据库中进行切换(开启事物禁用)
    引入xfire-all.jar后导致sping配置异常
    单点登录cas的最简单使用
    win10下cmd命令不能用
    前端json 两个重要的方法
    maven 工程下第三方jar 包的引入和打包 war
    idea 中main 方法不能运行
    从sqlServer 分页查询谈${}和#{}
    can与could区别
    线程同步与异步区别
  • 原文地址:https://www.cnblogs.com/csj2018/p/10878602.html
Copyright © 2011-2022 走看看