1. 程式人生 > >java 數字簽名

java 數字簽名

數字簽名是帶有金鑰(公鑰、私鑰)的訊息摘要演算法。主要作用是驗證資料的完整性、認證資料來源、抗否認。在數字簽名的實現中我們使用私鑰簽名、公鑰驗證。常用的數字簽名演算法包括RSA、DSA、ECDSA。

RSA

該演算法是數字簽名的經典演算法。主要包括MD和SHA兩類。

這裡寫圖片描述

Java實現RSA數字簽名如下:

package rsa2;

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 JavaRSA { private static String src = "What can I do for you?"; public static void main(String[] args) throws Exception { jdkRSA(); } public static void jdkRSA() throws Exception{ //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簽名:" + 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("數字簽名是否有效?" + bool); } }

執行結果:
這裡寫圖片描述

這裡寫圖片描述

DSA演算法

DSS(Digital Signature Standard),數字簽名標準,通過這個標準逐步形成了DSA(Digital Signature Algorithm),數字簽名算演算法。DSA僅僅包括數字簽名,不能進行加解密。實現方式如下:

這裡寫圖片描述

該演算法到的實現和RSA數字簽名的實現大同小異(只是在細節引數方面存在很少的差別)。見如下:

package 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 JavaDSA {

    private static String src = "Can I help you?";

    public static void main(String[] args) throws Exception {
        jdkDSA();
    }

    public static void jdkDSA() throws Exception{

        //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數字簽名:" + 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("數字簽名有效?" + bool);
    }
}

程式執行結果:
這裡寫圖片描述

ECDSA

微軟的Office、Windows作業系統的驗證就是ECDSA演算法——橢圓曲線數字簽名演算法(Elliptic Curve Digital Signature Algorithm),在2000年的時候稱為了ANSI和IEEE的標準。特點是:速度快、簽名短、強度高。在JDK1.7update4之後提供了對ECDSA的支援。該簽名的演算法也和RSA的數字簽名演算法也是大同小異。
這裡寫圖片描述

package ecdsa;

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.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 JavaECDSA {

    private static String src = "Hello,Objective C!";

    public static void main(String[] args) throws Exception {
        jdkECDSA();
    }

    public static void jdkECDSA() throws Exception{

        //1.初始化金鑰
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("EC");//引數是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("ECDSA簽名:" + 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("簽名的驗證結果:" + bool);
    }

}

執行結果:
這裡寫圖片描述

最後附上一系列Java加密的專案地址(包括Base64、對稱加密、非對稱加密、訊息摘要和數字簽名)。本文所需的jar檔案在專案的lib目錄中,jdk無政策訪問限制檔案在專案的ext目錄下。