发送报文时,发送方用一个哈希函数从报文文本中生成报文摘要,然后用自己的私人密钥对这个摘要进行加密,
这个加密后的摘要将作为报文的数字签名和报文一起发送给接收方,接收方首先用与发送方一样的哈希函数从接收到的原始报文中计算出报文摘要,
接着再用发送方的公用密钥来对报文附加的数字签名进行解密,如果这两个摘要相同、那么接收方就能确认该数字签名是发送方的。
数字签名的基础是公钥和私钥的非对称加密,发送者使用私钥加密消息摘要(签名),接收者使用公钥解密消息摘要以验证签名是否是某个人的。
基本步骤:
得到keyPairGenerator的实例对象,并调用其generateKeyPair()方法创建KeyPair对象。
调用KeyPair对象的getPrivate和getPublic方法,分别得到PrivateKey对象和PublicKey对象。
得到Signature的实例对象,调用其initSign()方法和指定PrivateKey对象,然后调用update方法和sign方法产生签名
调用Signature对象的initVerify()方法和指定PublicKey对象,然后调用update方法和verify()方法对原始数据的签名进行验证。
例子:
package com.study.security;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.security.Key;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
/**
* 数字签名
* 私钥签名公钥校验
* @author Administrator
*
*/
public class DigitSign {
public static void main(String[] args) throws Exception{
sign();
verify();
}
//签名
private static void sign()throws Exception{
KeyPairGenerator generator=KeyPairGenerator.getInstance("RSA");
KeyPair keyPair=generator.generateKeyPair();
PublicKey publicKey=keyPair.getPublic();
PrivateKey privateKey=keyPair.getPrivate();
Signature signature=Signature.getInstance("MD5withRSA");
signature.initSign(privateKey);
signature.update("hello java!".getBytes("UTF-8"));
byte[] signedResult=signature.sign();
//保存数据与公钥
saveKey(publicKey, "sign_public.key");
saveData(signedResult, "sign_data.data");
}
//校验
private static void verify()throws Exception{
byte[] data=readData("sign_data.data");
PublicKey publicKey=(PublicKey)readKey("sign_public.key");
Signature signature=Signature.getInstance("MD5withRSA");
signature.initVerify(publicKey);
signature.update("hello java!".getBytes("UTF-8"));
boolean isYourSign=signature.verify(data);
System.out.println("校验的结果:"+isYourSign);
}
//保存数据的方法
public static void saveData(byte[] results,String dataName)throws Exception{
FileOutputStream fosData=new FileOutputStream(dataName);
fosData.write(results);
fosData.close();
}
//恢复数据的方法
public static byte[] readData(String dataName)throws Exception{
FileInputStream fisDat= new FileInputStream(dataName);
//读二进制数据
ByteArrayOutputStream arrayOutputStream=new ByteArrayOutputStream();
int len=0;
byte[] data=new byte[1024];
while((len=fisDat.read(data))!=-1){
arrayOutputStream.write(data, 0, len);
}
byte[] result=arrayOutputStream.toByteArray();
arrayOutputStream.close();
fisDat.close();
return result;
}
//保存密钥的方法
public static void saveKey(Key key,String keyName) throws Exception{
FileOutputStream foskey=new FileOutputStream(keyName);
ObjectOutputStream oos=new ObjectOutputStream(foskey);
oos.writeObject(key);
oos.close();
foskey.close();
}
//恢复密钥的方法
public static Key readKey(String keyName) throws Exception{
FileInputStream fiskey=new FileInputStream(keyName);
ObjectInputStream oiskey=new ObjectInputStream(fiskey);
Key key=(Key)oiskey.readObject();
oiskey.close();
fiskey.close();
return key;
}
}