數字簽名算法主要包含RSA、DSA、ECDSA三種算法
1. 它的消息傳遞操作是:
- 由消息發送方建構密匙對,
- 由消息發送的一方公布公鑰至消息接收方,
- 消息發送方對消息用私鑰做簽名處理
- 消息接收方用公鑰對消息做驗證
2. RSA簽名算法主要分為MD系列和SHA系列。具體實作如下:
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiIwczX0xiRGZkRGZ0Xy9GbvNGL2EzXlpXazxSP9E0TzcmaNVzYE1EM4wmYwhGWhxGZzwEMW1mY1RzRapnTtxkb5ckYplTeMZTTINGMShUYfRHelRHLwEzX39GZhh2css2RkBnVHFmb1clWvB3MaVnRtp1XlBXe0xyayFWbyVGdhd3LcV2Zh1Wa9M3clN2byBXLzN3btg3PHBlSuATNzEjNyYTM0ITMxgTMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.jpg)
3. RSA的數字簽名代碼實作:
DSA簽名實作類似,ECDSA實作相比前兩者在密匙對成功的方式上存在差别。
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的倍數
* 範圍是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 待校驗的資料
* @param key 公鑰
* @param sign 資料簽名
* @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);
//校驗資料
Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
signature.initVerify(publicKey);
signature.update(data);
return signature.verify(sign);
}
/**
* 私鑰簽名
* @param data 待簽名資料
* @param key 私鑰
* @return byte[] 加密資料
* @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;
}
}