zoukankan      html  css  js  c++  java
  • Java实现数字签名

    、数字签名算法概述

       签名认证是对非对称加密技术与数字摘要技术的综合运用,指的是将通信内容的摘要信息使用发送者的私钥进行加密,然后将密文与原文一起传输给信息的接收者,接收者通过发送者的公钥信息来解密被加密的摘要作息,然后使用与发送者相同的摘要算法,对接收到的内容采用相同的方式方式产生摘要串,与解密的摘要串进行对比,如果相同,则说明接收到的内容是完整的,在传输过程中没有受到第三方的篡改,否则说明通信内容已被第三方修改。

       我们知道,每个人都有其特有的私钥,且都是对外界保密的,而通过私钥加密的信息,只能通过其对应的公钥来进行解密。因此,私钥可以代表私钥持有者的身份,可以通过私钥对应的公钥来对私钥拥有者的身份进行校验。通过数字签名,能够确认消息是消息发送方签名并发送过来的,因为其他人根本假冒不了消息发送方的签名,他们没有消息发送者的私钥。而不同的内容,摘要信息千差万别,通过数字摘要算法,可以确保传输内容的完整性,如果传输内容在中途被篡改了,对应的数字签名的值也将发生改变。

    数字签名:带有密钥(公钥,私钥)的消息摘要算法。私钥用于签名,公钥用于验证。

    数字签名的作用:

       验证数据的完整性,认证数据来源,抗否认。

    数字签名实现的具体原理:
       1、 将报文按双方约定的HASH算法计算得到一个固定位数的报文摘要。在数学上保证,只要改动报文中任何一位,重新计算出的报文摘要值就会与原先的值不相符。这样就保证了报文的不可更改性。(详见参考资料的"公钥密码技术原理"章节)
       2、 将该报文摘要值用发送者的私人密钥加密,然后连同原报文和数字证书(包含公钥)一起发送给接收者而产生的报文即称数字签名。
       3、接收方收到数字签名后,用同样的HASH算法对报文计算摘要值,然后与用发送者的公开密钥进行解密解开的报文摘要值相比较,如相等则说明报文确实来自所称的发送者。
       4、同时通过证书颁发机构CA确认证书的有效性即可确认发送的真实身份。

    数字签名的产生过程如图如示:

       

    数字签名的校验过程:

         

    常用的数字签名有:RSA、DSA、ECDSA

    常用的数字签名有:RSA、DSA、ECDSA

    二、数字签名算法—RSA

       RSA是目前最有影响力的公钥加密算法,它能够抵抗到目前为止已知的绝大多数密码攻击,已被ISO推荐为公钥数据加密标准。

       特性:安全性抗和否认性

       主要包括两类:MD、SHA

    具体算法如下图:

       

       例子:

    package rmd_intl_app.Test;
    import java.security.KeyFactory;
    import java.security.KeyPair;
    import java.security.KeyPairGenerator;
    import java.security.PrivateKey;
    import java.security.PublicKey;
    import java.security.Signature;
    import java.security.interfaces.RSAPrivateKey;
    import java.security.interfaces.RSAPublicKey;
    import java.security.spec.PKCS8EncodedKeySpec;
    import java.security.spec.X509EncodedKeySpec;
     
    import org.apache.commons.codec.binary.Hex;
     
    public class ImoocRSA {
        
        private static String src = "imooc security rsa";
     
        public static void main(String[] args) {
            jdkRSA();
        }
        
        public static void jdkRSA() {
            try {
                //1.初始化密钥
                KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
                keyPairGenerator.initialize(512);
                KeyPair keyPair = keyPairGenerator.generateKeyPair();
                RSAPublicKey rsaPublicKey = (RSAPublicKey)keyPair.getPublic();
                RSAPrivateKey rsaPrivateKey = (RSAPrivateKey)keyPair.getPrivate();
                
                //2.执行签名
                PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(rsaPrivateKey.getEncoded());
                KeyFactory keyFactory = KeyFactory.getInstance("RSA");
                PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
                Signature signature = Signature.getInstance("MD5withRSA");
                signature.initSign(privateKey);
                signature.update(src.getBytes());
                byte[] result = signature.sign();
                System.out.println("jdk rsa sign : " + Hex.encodeHexString(result));
                
                //3.验证签名
                X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(rsaPublicKey.getEncoded());
                keyFactory = KeyFactory.getInstance("RSA");
                PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
                signature = Signature.getInstance("MD5withRSA");
                signature.initVerify(publicKey);
                signature.update(src.getBytes());
                boolean bool = signature.verify(result);
                System.out.println("jdk rsa verify : " + bool);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
     
    }

    三、数字签名算法—DSA

       DSA是Schnorr和ElGamal签名算法的变种,被美国NIST作为DSfS(DigitalSignature Standard)。
       DSA是基于整数有限域离散对数难题的,其安全性与RSA相比差不多。DSA的一个重要特点是两个素数公开,这样,当使用别人的p和q时,即使不知道私钥,你也能确认它们是否是随机产生的,还是作了手脚。RSA却做不到。

        DSA仅包含数字签名

        具体算法如下图:

       

        例子:

    package com.imooc.security.dsa;
     
    import java.security.KeyFactory;
    import java.security.KeyPair;
    import java.security.KeyPairGenerator;
    import java.security.PrivateKey;
    import java.security.PublicKey;
    import java.security.Signature;
    import java.security.interfaces.DSAPrivateKey;
    import java.security.interfaces.DSAPublicKey;
    import java.security.spec.PKCS8EncodedKeySpec;
    import java.security.spec.X509EncodedKeySpec;
     
    import org.apache.commons.codec.binary.Hex;
     
    public class ImoocDSA {
        
        private static String src = "imooc security dsa";
     
        public static void main(String[] args) {
            jdkDSA();
        }
        
        public static void jdkDSA() {
            try {
                //1.初始化密钥
                KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("DSA");
                keyPairGenerator.initialize(512);
                KeyPair keyPair = keyPairGenerator.generateKeyPair();
                DSAPublicKey dsaPublicKey = (DSAPublicKey) keyPair.getPublic();
                DSAPrivateKey dsaPrivateKey = (DSAPrivateKey)keyPair.getPrivate();
                
                //2.执行签名
                PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(dsaPrivateKey.getEncoded());
                KeyFactory keyFactory = KeyFactory.getInstance("DSA");
                PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
                Signature signature = Signature.getInstance("SHA1withDSA");
                signature.initSign(privateKey);
                signature.update(src.getBytes());
                byte[] result = signature.sign();
                System.out.println("jdk dsa sign : " + Hex.encodeHexString(result));
                
                //3.验证签名
                X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(dsaPublicKey.getEncoded());
                keyFactory = KeyFactory.getInstance("DSA");
                PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
                signature = Signature.getInstance("SHA1withDSA");
                signature.initVerify(publicKey);
                signature.update(src.getBytes());
                boolean bool = signature.verify(result);
                System.out.println("jdk dsa verify : " + bool);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
     
    }

    四、数字签名算法—ECDSA

       ECDSA: 椭圆曲线数字签名算法(Elliptic Curve Digital Signatrue Algorithm)

       特点:速度快,强度高,签名短

       具体算法如下图:

    例子:

    package com.imooc.security.ecdsa;
     
    import java.security.KeyFactory;
    import java.security.KeyPair;
    import java.security.KeyPairGenerator;
    import java.security.NoSuchAlgorithmException;
    import java.security.PrivateKey;
    import java.security.PublicKey;
    import java.security.Signature;
    import java.security.interfaces.ECPrivateKey;
    import java.security.interfaces.ECPublicKey;
    import java.security.spec.PKCS8EncodedKeySpec;
    import java.security.spec.X509EncodedKeySpec;
     
    import org.apache.commons.codec.binary.Hex;
     
    public class ImoocECDSA {
        
        private static String src = "imooc security ecdsa";
     
        public static void main(String[] args) {
            jdkECDSA();
        }
        
        public static void jdkECDSA() {
            try {
                //1.初始化密钥
                KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("EC");
                keyPairGenerator.initialize(256);
                KeyPair keyPair = keyPairGenerator.generateKeyPair();
                ECPublicKey ecPublicKey = (ECPublicKey)keyPair.getPublic();
                ECPrivateKey ecPrivateKey = (ECPrivateKey)keyPair.getPrivate();
                
                //2.执行签名
                PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(ecPrivateKey.getEncoded());
                KeyFactory keyFactory = KeyFactory.getInstance("EC");
                PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
                Signature signature = Signature.getInstance("SHA1withECDSA");
                signature.initSign(privateKey);
                signature.update(src.getBytes());
                byte[] result = signature.sign();
                System.out.println("jdk ecdsa sign : " + Hex.encodeHexString(result));
                
                //3.验证签名
                X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(ecPublicKey.getEncoded());
                keyFactory = KeyFactory.getInstance("EC");
                PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
                signature = Signature.getInstance("SHA1withECDSA");
                signature.initVerify(publicKey);
                signature.update(src.getBytes());
                boolean bool = signature.verify(result);
                System.out.println("jdk ecdsa verify : " + bool);
            } catch (Exception e) {
                e.printStackTrace();
            }
            
        }
     
    }

    原文链接:https://blog.csdn.net/lovelichao12/article/details/75007189

  • 相关阅读:
    Python实现破解wifi密码8位(纯数字、数字与字母),并且记录破解开始和结束的时间
    WAPI相关了解及观点
    192.gulp-concat插件合并多个文件
    191.gulp处理JavaScript文件的任务
    190.gulp给文件重命名
    189.gulp创建处理css文件任务
    语句:{% url menu.url_name %}的作用
    Django2.0中的urlpattern匹配不输入任何网址时的写法
    python之函数递归
    python之全局变量与局部变量
  • 原文地址:https://www.cnblogs.com/nongzihong/p/12133324.html
Copyright © 2011-2022 走看看