數(shù)字簽名是一個帶有密鑰的消息摘要算法,這個密鑰包括了公鑰和私鑰,用于驗證數(shù)據(jù)完整性、認證數(shù)據(jù)來源和抗否認,遵循OSI參考模型、私鑰簽名和公鑰驗證。也是非對稱加密算法和消息摘要算法的結(jié)合體,常見的數(shù)字簽名算法主要有RSA、DSA、ECDSA三種。
RSA是目前計算機密碼學(xué)中最經(jīng)典算法,也是目前為止使用最廣泛的數(shù)字簽名算法,RSA數(shù)字簽名算法的密鑰實現(xiàn)與RSA的加密算法是一樣的,算法的名稱都叫RSA。
它的消息傳遞操作是:
1、由消息發(fā)送方構(gòu)建密匙對,
2、由消息發(fā)送的一方公布公鑰至消息接收方,
3、消息發(fā)送方對消息用私鑰做簽名處理
4、消息接收方用公鑰對消息做驗證
RSA的數(shù)字簽名代碼實現(xiàn):
DSA簽名實現(xiàn)類似,ECDSA實現(xiàn)相比前兩者在密匙對成功的方式上存在差別。
import org.apache.commons.codec.binary.Base64; import java.security.*; import java.security.interfaces.RSAPrivateKey; import java.security.interfaces.RSAPublicKey; import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.X509EncodedKeySpec; import java.util.HashMap; import java.util.Map; public class RSASignature { private static final String KEY_ALGORITHM="RSA"; private static final String SIGNATURE_ALGORITHM="MD5withRSA"; private static final String PUBLIC_KEY="RSAPublicKey"; private static final String PRIVATE_KEY="RSAPrivateKey"; /** * RSA密匙長度,默認是1024位,密匙長度必須是在64的倍數(shù) * 范圍是512--65536之間 * */ private static final int KEY_SIZE = 512; public static void main(String[] args) throws Exception { String str = "hello vison"; Map<String, Object> map = initKey(); byte[] privateKey = getPrivateKey(map); //簽名 byte[] signData = sign(str.getBytes(), privateKey); System.out.println("signData: " + Base64.encodeBase64(signData)); //校驗 byte[] pulicKey = getPulicKey(map); boolean status = verify(str.getBytes(), pulicKey, signData); System.out.println("verify result: " + status); } /** * * @param data 待校驗的數(shù)據(jù) * @param key 公鑰 * @param sign 數(shù)據(jù)簽名 * @return boolean 校驗成功返回true,否則返回false * @throws Exception */ public static boolean verify(byte[] data,byte[] key,byte[] sign)throws Exception{ //獲取公鑰 X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(key); KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec); //校驗數(shù)據(jù) Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM); signature.initVerify(publicKey); signature.update(data); return signature.verify(sign); } /** * 私鑰簽名 * @param data 待簽名數(shù)據(jù) * @param key 私鑰 * @return byte[] 加密數(shù)據(jù) * @throws Exception */ public static byte[] sign(byte[] data,byte[] key) throws Exception { //獲取私鑰 PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(key); KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec); //簽名 Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM); signature.initSign(privateKey); signature.update(data); return signature.sign(); } /** * 獲取私鑰 * @param keyMap * @return */ public static byte[] getPrivateKey(Map<String,Object> keyMap){ Key key = (Key) keyMap.get(PRIVATE_KEY); return key.getEncoded(); } /** * 獲取公鑰 * @param keyMap * @return */ public static byte[] getPulicKey(Map<String,Object> keyMap){ Key key = (Key) keyMap.get(PUBLIC_KEY); return key.getEncoded(); } /** * 初始化密匙對 * @return Map 密鑰map * @throws Exception */ public static Map<String,Object> initKey() throws Exception { //實例化密鑰對生成器 KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(KEY_ALGORITHM); //初始化 keyPairGenerator.initialize(KEY_SIZE); //生成密匙對 KeyPair keyPair = keyPairGenerator.genKeyPair(); //私鑰 RSAPrivateKey privateKey = (RSAPrivateKey)keyPair.getPrivate(); //公鑰 RSAPublicKey publicKey = (RSAPublicKey)keyPair.getPublic(); //封裝密鑰 HashMap<String, Object> map = new HashMap<>(2); map.put(PUBLIC_KEY,publicKey); map.put(PRIVATE_KEY,privateKey); return map; } }