數字簽名演算法
阿新 • • 發佈:2018-12-09
數字簽名演算法主要包含RSA、DSA、ECDSA三種演算法
1. 它的訊息傳遞操作是:
- 由訊息傳送方構建密匙對,
- 由訊息傳送的一方公佈公鑰至訊息接收方,
- 訊息傳送方對訊息用私鑰做簽名處理
- 訊息接收方用公鑰對訊息做驗證
2. RSA簽名演算法主要分為MD系列和SHA系列。具體實現如下:
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;
}
}