所谓数字签名就是信息发送者用其私钥对从所传报文中提取出的特征数据(或称数字指纹)进行 RSA 算法操作,以保证发信人无法抵赖曾发过该信息(即不可抵赖性),同时也确保信息报文在经签名后末被篡改(即完整性)。当信息接收者收到报文后,就可以用发送者的公钥对数字签名进行验证。
在数字签名中有重要作用的数字指纹是通过一类特殊的散列函数(HASH 函数)生成的,对这些 HASH 函数的特殊要求是:
1:接受的输入报文数据没有长度限制;
2:对任何输入报文数据生成固定长度的摘要(数字指纹)输出
3:从报文能方便地算出摘要;
4:难以对指定的摘要生成一个报文,而由该报文反推算出该指定的摘要;
5:两个不同的报文难以生成相同的摘要
代表:DSA
代码如下
package test; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.PrivateKey; import java.security.PublicKey; import java.security.Signature; public class DSA { public static void main(String[] args) { try { DSA my = new DSA(); my.run(); } catch (Exception e) { e.printStackTrace(); } } public void run() { // 数字签名生成密钥 // 第一步生成密钥对,如果已经生成过 , 本过程就可以跳过 // 对用户来讲 myprikey.dat 要保存在本地,而 mypubkey.dat 给发布给其它用户 if ((new java.io.File("myprikey.dat")).exists() == false) { if (generatekey() == false) { System.out.println("生成密钥对败"); return; } } // 第二步 , 此用户 // 从文件中读入私钥 , 对一个字符串进行签名后保存在一个文件 (myinfo.dat) 中 // 并且再把 myinfo.dat 发送出去,为了方便数字签名也放进了 myifno.dat 文件中 , 当然也可分别发送 try { ObjectInputStream in = new ObjectInputStream(new FileInputStream("myprikey.dat")); PrivateKey myprikey = (PrivateKey) in.readObject(); in.close(); String myinfo = "这是我的信息"; // 要签名的信息 // 用私钥对信息生成数字签名 Signature signet = Signature.getInstance("DSA"); signet.initSign(myprikey); signet.update(myinfo.getBytes()); byte[] signed = signet.sign(); // 对信息的数字签名 System.out.println("signed( 签名内容 )=" + byte2hex(signed)); // 把信息和数字签名保存在一个文件中 ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("myinfo.dat")); out.writeObject(myinfo); out.writeObject(signed); out.close(); System.out.println("签名并生成文件成功"); } catch (java.lang.Exception e) { e.printStackTrace(); System.out.println("签名并生成文件失败"); } // 第三步 获得信息检查 // 其他人通过公共方式得到此户的公钥和文件 // 其他人用此户的公钥 , 对文件进行检查 , 如果成功说明是此用户发布的信息 . try { ObjectInputStream in = new ObjectInputStream(new FileInputStream("mypubkey.dat")); PublicKey pubkey = (PublicKey) in.readObject(); in.close(); System.out.println(pubkey.getFormat()); in = new ObjectInputStream(new FileInputStream("myinfo.dat")); String info = (String) in.readObject(); byte[] signed = (byte[]) in.readObject(); in.close(); Signature signetcheck = Signature.getInstance("DSA"); signetcheck.initVerify(pubkey); signetcheck.update(info.getBytes()); if (signetcheck.verify(signed)) { System.out.println("info=" + info); System.out.println("签名正常"); } else System.out.println("非签名正常"); } catch (java.lang.Exception e) { e.printStackTrace(); } ; } // 生成一对文件 myprikey.dat 和 mypubkey.dat 私钥和公钥 // 公钥要用户发送 ( 文件 , 网络等方法 ) 给其它用户 , 私钥保存在本地 public boolean generatekey() { try { KeyPairGenerator keygen = KeyPairGenerator.getInstance("DSA"); keygen.initialize(512); KeyPair keys = keygen.genKeyPair(); PublicKey pubkey = keys.getPublic(); PrivateKey prikey = keys.getPrivate(); ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("myprikey.dat")); out.writeObject(prikey); out.close(); System.out.println("写入对象 prikeys ok"); out = new ObjectOutputStream(new FileOutputStream("mypubkey.dat")); out.writeObject(pubkey); out.close(); System.out.println("写入对象 pubkeys ok"); System.out.println("生成密钥对成功"); return true; } catch (java.lang.Exception e) { e.printStackTrace(); System.out.println("生成密钥对失败"); return false; } } public String byte2hex(byte[] b) { String hs = ""; String stmp = ""; for (int n = 0; n < b.length; n++) { stmp = (java.lang.Integer.toHexString(b[n] & 0XFF)); if (stmp.length() == 1) hs = hs + "0" + stmp; else hs = hs + stmp; if (n < b.length - 1) hs = hs + ":"; } return hs.toUpperCase(); } }
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持自学编程网。
- 本文固定链接: https://zxbcw.cn/post/197786/
- 转载请注明:必须在正文中标注并保留原文链接
- QQ群: PHP高手阵营官方总群(344148542)
- QQ群: Yii2.0开发(304864863)