Java安全之数字签名
数字签名能够验证数据完整性、认证数据来源,并起到抗否认的作用,这3点与OSI参考模型中的数据完整性服务、认证(鉴别)服务和抗否认性服务相对应。消息摘要算法是验证数据完整性的最佳算法,因此,该算法成为数字签名中的必要组成部分。
基于数据完整性验证,我们希望数据的发送方可以对自己所发送的数据做相应的签名处理,同时给出对应的凭证(签名),并且数据的接收方可以验证该签名是否与数据发送方发送的数据相符。如何任何人都可以进行签名处理,那么签名就失去了验证的意义。所以,签名操作只能是由数据发送方来完成,而验证签名的操作则由数据接收方来完成。既然签名操作仅限于数据发送方,那么签名操作本身只能是基于数据发送方的某些私有信息完成的。并且,用于验证操作的相关信息是由数据发送方公布给数据接收方的。
用于签名的相关信息私有,用于验证的相关信息公开,且这两种信息必须成对出现。非对称加密中的公钥与私钥恰好满足这种关系,因此成为了数字签名中的重要元素。数字签名算法包含签名与验证两项操作,遵循“私钥签名,公钥验证”的签名/验证方式,签名时需要使用私钥和待签名数据,验证时则需要公钥、签名值和待签名验证数据,其核心算法主要是消息摘要算法。
下面就看一个Java使用数字签名的例子:
package com.xtayfjpk.security;
import java.io.EOFException;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.security.Key;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.util.ArrayList;
import java.util.List;
import org.junit.Test;
public class SignatureTest {
private static final String KEY_PAIR_ALGOGRITHM = "DSA";
private static final String SIGNATURE_ALGOGRITHM = "SHA1withDSA";
private static final String PUBLIC_KEY_PATH = "public.key";
private static final String PRIVATE_KEY_PATH = "private.key";
private static final String SIGNATURE_PATH = "signature.dat";
@Test //生成公钥与私钥并保存至文件
public void testGenerateKeyPair() throws Exception {
KeyPairGenerator generator = KeyPairGenerator.getInstance(KEY_PAIR_ALGOGRITHM);
KeyPair keyPair = generator.generateKeyPair();
PublicKey publicKey = keyPair.getPublic();
PrivateKey privateKey = keyPair.getPrivate();
writeKey(PUBLIC_KEY_PATH, publicKey);
writeKey(PRIVATE_KEY_PATH, privateKey);
}
@Test
public void testSign() throws Exception {
String myInfo = "《Java》精讲公从号";
PrivateKey privateKey = PrivateKey.class.cast(readKey(PRIVATE_KEY_PATH));
//初始化一个Signature对象,并用私钥对信息签名,JDK(7)支持的数字签名算法有很多,
//具体可参见http://docs.oracle.com/javase/7/docs/technotes/guides/security/StandardNames.html#Signature
Signature signature = Signature.getInstance(SIGNATURE_ALGOGRITHM);
//私钥签名
signature.initSign(privateKey);
//更新待签名数据
signature.update(myInfo.getBytes());
//得到数字签名
byte[] signed = signature.sign();
//把信息和签名保存在一个文件中
writeObjects(SIGNATURE_PATH, myInfo, signed);
}
@Test
public void testVerify() throws Exception {
PublicKey publicKey = PublicKey.class.cast(readKey(PUBLIC_KEY_PATH));
List
------------------ END ---------------------
及时获取更多精彩文章,请扫码关注如下公众号《Java精讲》: