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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM