";
}
returnhs.toUpperCase();
}
}
2.3.数字签名DSA
对于一个用户来讲首先要生成他的密钥对,并且分别保存
生成一个KeyPairGenerator实例
java.security.KeyPairGeneratorkeygen=java.security.KeyPairGenerator.getInstance("DSA");
//如果设定随机产生器就用如相代码初始化
SecureRandomsecrand=newSecureRandom();
secrand.setSeed("tttt".getBytes());//初始化随机产生器
keygen.initialize(512,secrand);//初始化密钥生成器
//否则
keygen.initialize(512);
//生成密钥公钥pubkey和私钥prikey
KeyPairkeys=keygen.generateKeyPair();//生成密钥组
PublicKeypubkey=keys.getPublic();
PrivateKeyprikey=keys.getPrivate();
//分别保存在myprikey.dat和mypubkey.dat中,以便下次不在生成
//(生成密钥对的时间比较长
java.io.ObjectOutputStreamout=newjava.io.ObjectOutputStream(
newjava.io.FileOutputStream("myprikey.dat"));
out.writeObject(prikey);
out.close();
out=newjava.io.ObjectOutputStream(newjava.io.FileOutputStream("mypubkey.dat"));
out.writeObject(pubkey);
out.close();
用他私人密钥(prikey)对他所确认的信息(info)进行数字签名产生一个签名数组
从文件中读入私人密钥(prikey)
java.io.ObjectInputStreamin=newjava.io.ObjectInputStream(
newjava.io.FileInputStream("myprikey.dat"));
PrivateKeymyprikey=(PrivateKey)in.readObject();
in.close();
初始一个Signature对象,并用私钥对信息签名
java.security.Signaturesignet=java.security.Signature.getInstance("DSA");
signet.initSign(myprikey);
signet.update(myinfo.getBytes());
byte[]signed=signet.sign();
把信息和签名保存在一个文件中(myinfo.dat)
java.io.ObjectOutputStreamout=newjava.io.ObjectOutputStream(
newjava.io.FileOutputStream("myinfo.dat"));
out.writeObject(myinfo);
out.writeObject(signed);
out.close();
把他的公钥的信息及签名发给其它用户
其他用户用他的公共密钥(pubkey)和签名(signed)和信息(info)进行验证是否由他签名的信息
读入公钥java.io.ObjectInputStreamin=newjava.io.ObjectInputStream(newjava.io.FileInputStream("mypubkey.dat"));PublicKeypubkey=(PublicKey)in.readObject();in.close();
读入签名和信息in=newjava.io.ObjectInputStream(newjava.io.FileInputStream("myinfo.dat"));Stringinfo=(String)in.readObject();byte[]signed=(byte[])in.readObject();in.close();
初始一个Signature对象,并用公钥和签名进行验证java.security.Signaturesignetcheck=java.security.Signature.getInstance("DSA");signetcheck.initVerify(pubkey);signetcheck.update(info.getBytes());if(signetcheck.verify(signed)){System.out.println("签名正常");}
对于密钥的保存本文是用对象流的方式保存和传送的,也可可以用编码的方式保存.注意要importjava.security.spec.*importjava.security.*
具休说明如下
publickey是用X.509编码的,例码如下:
byte[]bobEncodedPubKey=mypublic.getEncoded();//生成编码
//传送二进制编码
//以下代码转换编码为相应key对象
X509EncodedKeySpecbobPubKeySpec=newX509EncodedKeySpec(bobEncodedPubKey);
KeyFactorykeyFactory=KeyFactory.getInstance("DSA");
PublicKeybobPubKey=keyFactory.generatePublic(bobPubKeySpec);
对于Privatekey是用PKCS#8编码,例码如下:
byte[]bPKCS=myprikey.getEncoded();
//传送二进制编码
//以下代码转换编码为相应key对象
PKCS8EncodedKeySpecpriPKCS8=newPKCS8EncodedKeySpec(bPKCS);
KeyFactorykeyf=KeyFactory.getInstance("DSA");
PrivateKeyotherprikey=keyf.generatePrivate(priPKCS8);
常用API
java.security.KeyPairGenerator密钥生成器类publicstaticKeyPairGeneratorgetInstance(Stringalgorithm)throwsNoSuchAlgorithmException以指定的算法返回一个KeyPairGenerator对象参数:
algorithm算法名.如:
"DSA","RSA"
publicvoidinitialize(intkeysize)
以指定的长度初始化KeyPairGenerator对象,如果没有初始化系统以1024长度默认设置
参数:
keysize算法位长.其范围必须在512到1024之间,且必须为64的倍数
publicvoidinitialize(intkeysize,SecureRandomrandom)以指定的长度初始化和随机发生器初始化KeyPairGenerator对象参数:
keysize算法位长.其范围必须在512到1024之间,且必须为64的倍数random一个随机位的来源(对于initialize(intkeysize)使用了默认随机器
publicabstractKeyPairgenerateKeyPair()产生新密钥对
java.security.KeyPair密钥对类publicPrivateKeygetPrivate()返回私钥
publicPublicKeygetPublic()返回公钥
java.security.Signature签名类publicstaticSignaturegetInstance(Stringalgorithm)throwsNoSuchAlgorithmException返回一个指定算法的Signature对象参数algorithm如:
"DSA"
publicfinalvoidinitSign(PrivateKeyprivateKey)throwsInvalidKeyException用指定的私钥初始化参数:
privateKey所进行签名时用的私钥
publicfinalvoidupdate(bytedata)throwsSignatureExceptionpublicfinalvoidupdate(byte[]data)throwsSignatureExceptionpublicfinalvoidupdate(byte[]data,intoff,intlen)throwsSignatureException添加要签名的信息
publicfinalbyte[]sign()throwsSignatureException返回签名的数组,前提是initSign和update
publicfinalvoidinitVerify(PublicKeypublicKey)throwsInvalidKeyException用指定的公钥初始化参数:
publicKey验证时用的公钥
publicfinalbooleanverify(byte[]signature)throwsSignatureException验证签名是否有效,前提是已经initVerify初始化参数:
signature签名数组
importjava.security.*;
importjava.security.spec.*;
publicclasstestdsa{
publicstaticvoidmain(String[]args)throwsjava.security.NoSuchAlgorithmException,
java.lang.Exception{
testdsamy=newtestdsa();
my.run();
}
publicvoidrun()
{
//数字签名生成密钥
//第一步生成密钥对,如果已经生成过,本过程就可以跳过,
//对用户来讲myprikey.dat要保存在本地
//而mypubkey.dat给发布给其它用户
if((newjava.io.File("myprikey.dat")).exists()==false){
if(generatekey()==false){
System.out.println("生成密钥对败");
return;
};
}
//第二步,此用户
//从文件中读入私钥,对一个字符串进行签名后保存在一个文件(myinfo.dat)中
//并且再把myinfo.dat发送出去
//为了方便数字签名也放进了myifno.dat文件中,当然也可分别发送
try{
java.io.ObjectInputStreamin=newjava.io.ObjectInputStream(
newjava.io.FileInputStream("myprikey.dat"));
PrivateKeymyprikey=(PrivateKey)in.readObject();
in.close();
//java.security.spec.X509EncodedKeySpecpubX509=
//newjava.security.spec.X509EncodedKeySpec(bX509);
//java.security.spec.X509EncodedKeySpecpubkeyEncode=
//java.security.spec.X509EncodedKeySpec
Stringmyinfo="这是我的信息";//要签名的信息
//用私钥对信息生成数字签名
java.security.Signaturesignet=java.security.Signature.getInstance("DSA");
signet.initSign(myprikey);
signet.update(myinfo.getBytes());
byte[]signed=signet.sign();//对信息的数字签名
System.out.println("signed(签名内容)="+byte2hex(signed));
//把信息和数字签名保存在一个文件中
java.io.ObjectOutputStreamout=newjava.io.ObjectOutputStream(
newjava.io.FileOutputStream("myinfo.dat"));
out.writeObject(myinfo);
out.writeObject(signed);
out.close();
System.out.println("签名并生成文件成功");
}
catch(java.lang.Exceptione){
e.printStackTrace();
System.out.println("签名并生成文件失败");
};
//第三步
//其他人通过公共方式得到此户的公钥和文件
//其他人用此户的公钥,对文件进行检查,如果成功说明是此用户发布的信息.
//
try{
java.io.ObjectInputStreamin=newjava.io.ObjectInputStream(
newjava.io.FileInputStream("mypubkey.dat"));
PublicKeypubkey=(PublicKey)in.readObject();
in.close();
System.out.println(pubkey.getFormat());
in=newjava.io.ObjectInputStream(newjava.io.