Java安全之数字签名
2016-10-18 10:10
423 查看
Java安全之数字签名
数字签名是一种安全措施,分为:消息摘要和消息签名。概念:
1、消息摘要:是一种算法,分为MD5/SHA算法,无论原始数据多长,消息摘要的结果都是固定长度的;原始数据任意bit位的变化,都会导致消息摘要的结果有很大的不同,且根据结果推算出原始数据的概率极低。消息摘要可以看作原始数据的指纹,指纹不同则原始数据不同。主要作用用来防止消息在传递途中被“第三者”篡改了。2、消息签名:其基础是公钥和私钥的非对称加密,发送者使用私钥加密消息摘要,接收者使用公钥解密消息摘要以验证签名是否是某个人的。主要作用是验证发消息者的身份,确保消息来源的可靠性。
图解:
1、鲍勃有两把钥匙,一把是公钥,另一把是私钥。2、鲍勃把公钥送给他的朋友们—-帕蒂、道格、苏珊—-每人一把。
3、鲍勃给苏珊写信,决定采用 “数字签名”。他写完后先用Hash函数,生成信件的摘要(digest)
这个过程用到的哈希算法主要有MD5算法和SHA算法。
4、然后,鲍勃使用私钥,对这个摘要加密,生成”消息签名”(signature)。
5、鲍勃将这个签名,附在信件下面,一起发给苏珊。
6、苏珊收信后,取下消息签名,用鲍勃的公钥解密,得到信件的摘要。由此证明,这封信确实是鲍勃发出的。
7、苏珊再对信件本身使用Hash函数,将得到的结果,与上一步得到的摘要进行对比。如果两者一致,就证明这封信未被修改过。
这样一个完整过程就完成了对消息来源者身份的确定和对消息内容安全性的验证。
但是,这样并不能保证绝对安全,假如,道格想欺骗苏珊,他偷偷使用了苏珊的电脑,用自己的公钥换走了鲍勃的公钥。此时,苏珊实际拥有的是道格的公钥,但是还以为这是鲍勃的公钥。因此,道格就可以冒充鲍勃,用自己的私钥做成”数字签名”,写信给苏珊,让苏珊用假的鲍勃公钥进行解密。解决这个问题就涉及到认证,这里我们先不做谈论。
示例代码:
1、生成消息摘要的代码:import java.io.IOException; import java.nio.file.Files; import java.nio.file.Paths; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; public class Digest { private static String[] arg={"D:\\英文\\java\\JavaInterview\\阿房宫赋.txt","SHA-1","MD5"}; public static void main(String[] args) throws NoSuchAlgorithmException, IOException { // TODO Auto-generated method stub String sha=arg.length>=2?arg[1]:"SHA-1"; d3f5 String md5=arg.length>=3?arg[2]:"MD5"; MessageDigest alg1=MessageDigest.getInstance(sha); MessageDigest alg2=MessageDigest.getInstance(md5); byte[] input=Files.readAllBytes(Paths.get(arg[0])); byte[] hash1=alg1.digest(input); byte[] hash2=alg2.digest(input); String d1=""; for(int i=0;i<hash1.length;i++){ int v=hash1[i]&0xFF; if(v<16) d1+="0"; d1+=Integer.toString(v,16).toUpperCase()+""; } String d2=""; for(int i=0;i<hash2.length;i++){ int v=hash2[i]&0xFF; if(v<16) d2+="0"; d2+=Integer.toString(v,16).toUpperCase()+""; } System.out.println("SHA-1算法生成的消息摘要: "+d1); System.out.println("MD5算法生成的消息摘要: "+d2); } }
运行结果:
SHA-1算法生成的消息摘要: 42109004CF53C57A5667D94420063D1D5B762DB1 MD5算法生成的消息摘要: FD0B8405534503F587F22FD73038E03B
从结果可以看出,SHA-1算法生成的消息摘要要稍微长一些,安全新也自然高一些,而且目前MD5算法被找到了一些规律,可靠性更差了,一般推荐使用SHA-1算法。
2、消息签名的代码:
import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.security.InvalidKeyException; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.NoSuchAlgorithmException; import java.security.PrivateKey; import java.security.PublicKey; import java.security.Signature; import java.security.SignatureException; public class SignatureTest { public static void main(String[] args) throws NoSuchAlgorithmException, InvalidKeyException, SignatureException, ClassNotFoundException, IOException { // 通用处理方式 KeyPairGenerator keyPairGenerator=KeyPairGenerator.getInstance("RSA"); KeyPair keyPair=keyPairGenerator.generateKeyPair(); PrivateKey privateKey=keyPair.getPrivate(); PublicKey publicKey=keyPair.getPublic(); Signature signature=Signature.getInstance("MD5withRSA"); signature.initSign(privateKey); byte[] src=new byte[]{1,2,3,4,5,6,7}; signature.update(src); byte[] signed=signature.sign(); signature.initVerify(publicKey); signature.update(src); System.out.println(signature.verify(signed)); // 保存原始数据,签名,公钥,秘钥 FileOutputStream foutsrc=new FileOutputStream("src.txt"); FileOutputStream foutsigned=new FileOutputStream("signed.dat"); foutsrc.write(src); foutsigned.write(signed); foutsigned.close(); foutsrc.close(); FileOutputStream outPublicKey=new FileOutputStream("public.key"); ObjectOutputStream objOut=new ObjectOutputStream(outPublicKey); objOut.writeObject(publicKey); objOut.close(); outPublicKey.close(); FileOutputStream outprivateKey=new FileOutputStream("private.key"); ObjectOutputStream objOut1=new ObjectOutputStream(outprivateKey); objOut1.writeObject(privateKey); objOut1.close(); outprivateKey.close(); // 流数据的特殊处理 sign(); verify(); } private static void verify() throws IOException, ClassNotFoundException, NoSuchAlgorithmException, InvalidKeyException, SignatureException { FileInputStream fisPublicKey=new FileInputStream("public.key"); ObjectInputStream oisPublicKey=new ObjectInputStream(fisPublicKey); PublicKey publicKey=(PublicKey) oisPublicKey.readObject(); oisPublicKey.close(); fisPublicKey.close(); Signature signature=Signature.getInstance("MD5withRSA"); signature.initVerify(publicKey); FileInputStream fis=new FileInputStream("src.txt"); byte[] src=new byte[1024]; int len=0; while((len=fis.read(src))!=-1){ signature.update(src,0,len); } fis.close(); FileInputStream fisSigned=new FileInputStream("signed.dat"); byte[] signed=new byte[fisSigned.available()]; int readed=0; int total=0; System.out.println(signed.length); while(total<signed.length){ // 此方法的第三个参数 len 长度不能大于 b.length-off,并且 len 等于 0 时 直接返回,所以不能用 while(readed!=-1)进行判断 readed=fisSigned.read(signed,total,signed.length-total); total+=readed; } fisSigned.close(); System.out.println(signature.verify(signed)); } private static void sign() throws IOException, ClassNotFoundException, NoSuchAlgorithmException, InvalidKeyException, SignatureException { FileInputStream fisPrivateKey=new FileInputStream("private.key"); ObjectInputStream oisPrivateKey=new ObjectInputStream(fisPrivateKey); PrivateKey privateKey=(PrivateKey) oisPrivateKey.readObject(); oisPrivateKey.close(); fisPrivateKey.close(); Signature signature=Signature.getInstance("MD5withRSA"); signature.initSign(privateKey); FileInputStream fis=new FileInputStream("src.txt"); byte[] src=new byte[1024]; int len=0; while((len=fis.read(src))!=-1){ signature.update(src,0,len); } fis.close(); byte[] signed=signature.sign(); System.out.println(signed.length); FileOutputStream fos=new FileOutputStream("signed.dat"); fos.write(signed); fos.close(); } }
运行结果:
true 128 128 true
本示例代码中,展现了两种方式的签名,第一种是通用方式:直接对已知的内容进行加密;第二种方式是通过数据流的方式,对读取的文件中的内容进行加密,加密完成之后再存入文件,然后进行文件传输,接收端又读取接收文件,再进行解密验证。
相关文章推荐
- java安全之数字签名及证书
- java-信息安全(六)-基于RSA理解数字签名示例
- JAVA高级【7.3】《Java核心技术2》安全-Java 数字签名原理及产生
- java安全架构____java DSA数字签名原理
- java-信息安全(四)-数据签名、数字证书
- 详解Java数字签名提供XML安全
- 用Java数字签名提供XML安全
- 用Java数字签名提供XML安全
- Java安全之数字签名
- 用Java数字签名提供XML安全
- Java安全通信、数字证书及应用实践
- java安全通信、数字证书及数字证书应用实践
- 在Eclipse的Web项目中java里面使用ant进行数字签名步骤详解
- Java2下Applet数字签名具体实现方法
- Java加密和数字签名编程快速入门
- Java2下Applet数字签名具体实现方法
- Java安全通信、数字证书及数字证书应用实践
- Java加密和数字签名编程快速入门(1/3)
- 在java中编程实现数字签名系统
- 一个基于RSA算法的Java数字签名例子