1. 程式人生 > >數字簽名(2):DSA

數字簽名(2):DSA

一.DSA :

     Digital Signature Algorithm (DSA)是Schnorr和ElGamal簽名演算法的變種,被美國NIST作為DSfS(DigitalSignature Standard)。

二.模型

三.具體的演算法,實現方,祕鑰長度

演算法 金鑰長度 預設長度 簽名長度 實現的方
SHA1withDSA 512-65536
(64的整數倍)
1024 同金鑰 JDK
SHA224withDSA 同上 1024 同金鑰 BC
SHA256withDSA ... 1024 同金鑰 BC
SHA384withDSA ... 1024 同金鑰 BC
SHA512withDSA ... 1024 同金鑰 BC

四.具體的程式碼實現(java):

import java.security.InvalidKeyException;
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.SignatureException;
import java.security.interfaces.DSAPrivateKey;
import java.security.interfaces.DSAPublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;

import org.apache.commons.codec.binary.Base64;

public class DSA {

	static String src = "歐陽草帽";
	
	public static void main(String[] args) throws Exception {
		// TODO Auto-generated method stub
		
		// 獲取公鑰、私鑰  
		KeyPair keyPair = getKeyPair();
		
		DSAPublicKey dsaPublicKey = getRSPublicKey(keyPair);
		DSAPrivateKey dsaPrivateKey = getESAPrivateKey(keyPair);
		byte [] publicKeyEnc = dsaPublicKey.getEncoded();   // 公鑰
		byte [] privateKeyEnc = dsaPrivateKey.getEncoded(); //私鑰
		
		//執行簽名 
		byte[] result = sign(privateKeyEnc);
		System.out.println("簽名後的資料:"+Base64.encodeBase64String(result));
		
		//驗證簽名
		boolean ok = verify(publicKeyEnc, result);
		System.out.println("簽名驗證的結果:" + ok);
	}
	/**
	 * 驗證簽名
	 * @param publicKeyEnc
	 * @param result
	 * @return
	 * @throws NoSuchAlgorithmException
	 * @throws InvalidKeySpecException
	 * @throws InvalidKeyException
	 * @throws SignatureException
	 */
	public static boolean verify(byte[] publicKeyEnc, byte[] result)
			throws NoSuchAlgorithmException, InvalidKeySpecException,
			InvalidKeyException, SignatureException {
		X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(publicKeyEnc);
		KeyFactory keyFactory = KeyFactory.getInstance("DSA");
		PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
		Signature signature = Signature.getInstance("SHA1withDSA");
		signature.initVerify(publicKey);
		signature.update(src.getBytes());
		boolean ok = signature.verify(result);  // 驗證結果 
		return ok;
	}

	/**
	 * 執行簽名
	 * @param privateKeyEnc
	 * @return
	 * @throws NoSuchAlgorithmException
	 * @throws InvalidKeySpecException
	 * @throws InvalidKeyException
	 * @throws SignatureException
	 */
	public static byte[] sign(byte[] privateKeyEnc)
			throws NoSuchAlgorithmException, InvalidKeySpecException,
			InvalidKeyException, SignatureException {
		KeyFactory keyFactory = KeyFactory.getInstance("DSA");
		PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(privateKeyEnc);
		PrivateKey priKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
		//構建簽名 
		Signature signature = Signature.getInstance("SHA1withDSA");
		signature.initSign(priKey);
		signature.update(src.getBytes());
		byte [] result = signature.sign();   // 簽名後的資料資訊
		return result;
	}
	
	/**
	 * 生成私鑰
	 * @param keyPair
	 * @return
	 */
	public static DSAPrivateKey getESAPrivateKey(KeyPair keyPair) {
		DSAPrivateKey dsaPrivateKey = (DSAPrivateKey) keyPair.getPrivate();
		return dsaPrivateKey;
	}
	
	/**
	 * 生成公鑰
	 * @param keyPair
	 * @return
	 */
	public static DSAPublicKey getRSPublicKey(KeyPair keyPair) {
		DSAPublicKey dsaPublicKey = (DSAPublicKey) keyPair.getPublic();
		return dsaPublicKey;
	}

	/**
	 * 生成祕鑰對的材料 
	 * @return
	 * @throws NoSuchAlgorithmException
	 */
	private static KeyPair getKeyPair() throws NoSuchAlgorithmException {
		KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("DSA");
		keyPairGenerator.initialize(512);
		KeyPair keyPair = keyPairGenerator.generateKeyPair();
		return keyPair;
	}
}
輸出結果:

簽名後的資料:MC0CFCNn2mkuMmv61IbezkNhK2DRvPKxAhUAjmh0dBZinEg+kg5e6bMwNqFmx+M=
簽名驗證的結果:true