DSA數字簽名,非對稱加密的另外一種實現。
DSA
DSA-Digital Signature Algorithm 是Schnorr和ElGamal簽名算法的變種,被美國NIST做爲DSS(DigitalSignature Standard)。簡單的說,這是一種更高級的驗證方式,用做數字簽名。不僅僅只有公鑰、私鑰,還有數字簽名。私鑰加密生成數字簽名,公鑰驗證數據及籤 名。若是數據和簽名不匹配則認爲驗證失敗!數字簽名的做用就是校驗數據在傳輸過程當中不被修改。數字簽名,是單向加密的升級!
java
經過java代碼實現以下:git
package com.java.security; import java.security.Key; import java.security.KeyFactory; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.PrivateKey; import java.security.PublicKey; import java.security.SecureRandom; 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 java.util.HashMap; import java.util.Map; /** * DSA安全編碼組件 * */ public class DSAUtil extends EncryptUtils { public static final String ALGORITHM = "DSA"; /** * 默認密鑰字節數 */ private static final int KEY_SIZE = 1024; /** * 默認種子 */ private static final String DEFAULT_SEED = "0f22507a10bbddd07d8a3082122966e3"; private static final String PUBLIC_KEY = "DSAPublicKey"; private static final String PRIVATE_KEY = "DSAPrivateKey"; /** * 用私鑰對信息生成數字簽名 * * @param data 加密數據 * @param privateKey 私鑰 * * @return * @throws Exception */ public static String sign(byte[] data, String privateKey) throws Exception { // 解密由base64編碼的私鑰 byte[] keyBytes = decryptBASE64(privateKey); // 構造PKCS8EncodedKeySpec對象 PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes); // KEY_ALGORITHM 指定的加密算法 KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM); // 取私鑰匙對象 PrivateKey priKey = keyFactory.generatePrivate(pkcs8KeySpec); // 用私鑰對信息生成數字簽名 Signature signature = Signature.getInstance(keyFactory.getAlgorithm()); signature.initSign(priKey); signature.update(data); return encryptBASE64(signature.sign()); } /** * 校驗數字簽名 * * @param data 加密數據 * @param publicKey 公鑰 * @param sign 數字簽名 * @return 校驗成功返回true 失敗返回false * @throws Exception * */ public static boolean verify(byte[] data, String publicKey, String sign) throws Exception { // 解密由base64編碼的公鑰 byte[] keyBytes = decryptBASE64(publicKey); // 構造X509EncodedKeySpec對象 X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes); // ALGORITHM 指定的加密算法 KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM); // 取公鑰匙對象 PublicKey pubKey = keyFactory.generatePublic(keySpec); Signature signature = Signature.getInstance(keyFactory.getAlgorithm()); signature.initVerify(pubKey); signature.update(data); // 驗證簽名是否正常 return signature.verify(decryptBASE64(sign)); } /** * 生成密鑰 * * @param seed * 種子 * @return 密鑰對象 * @throws Exception */ public static Map<String, Object> initKey(String seed) throws Exception { KeyPairGenerator keygen = KeyPairGenerator.getInstance(ALGORITHM); // 初始化隨機產生器 SecureRandom secureRandom = new SecureRandom(); secureRandom.setSeed(seed.getBytes()); keygen.initialize(KEY_SIZE, secureRandom); KeyPair keys = keygen.genKeyPair(); DSAPublicKey publicKey = (DSAPublicKey) keys.getPublic(); DSAPrivateKey privateKey = (DSAPrivateKey) keys.getPrivate(); Map<String, Object> map = new HashMap<String, Object>(2); map.put(PUBLIC_KEY, publicKey); map.put(PRIVATE_KEY, privateKey); return map; } /** * 默認生成密鑰 * * @return 密鑰對象 * @throws Exception */ public static Map<String, Object> initKey() throws Exception { return initKey(DEFAULT_SEED); } /** * 取得私鑰 * @param keyMap * @return * @throws Exception */ public static String getPrivateKey(Map<String, Object> keyMap) throws Exception { Key key = (Key) keyMap.get(PRIVATE_KEY); return encryptBASE64(key.getEncoded()); } /** * 取得公鑰 * @param keyMap * @return * @throws Exception */ public static String getPublicKey(Map<String, Object> keyMap) throws Exception { Key key = (Key) keyMap.get(PUBLIC_KEY); return encryptBASE64(key.getEncoded()); } public static void main(String[] args) throws Exception{ String inputStr = "abc"; byte[] data = inputStr.getBytes(); // 構建密鑰 Map<String, Object> keyMap = initKey(); // 得到密鑰 String publicKey = getPublicKey(keyMap); String privateKey = getPrivateKey(keyMap); System.err.println("公鑰:\r" + publicKey); System.err.println("私鑰:\r" + privateKey); // 產生簽名 String sign = sign(data, privateKey); System.err.println("簽名:\r" + sign); // 驗證簽名 boolean status = verify(data, publicKey, sign); System.err.println("狀態:\r" + status); } }