java 數字簽名
阿新 • • 發佈:2019-01-10
數字簽名是帶有金鑰(公鑰、私鑰)的訊息摘要演算法。主要作用是驗證資料的完整性、認證資料來源、抗否認。在數字簽名的實現中我們使用私鑰簽名、公鑰驗證。常用的數字簽名演算法包括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目錄下。