java安全--数字签名

来源:互联网 发布:和男闺蜜做过的事 知乎 编辑:程序博客网 时间:2024/06/08 18:44

        假如发送方想把一份报文发送给接收方,在发送报文前,发送方用一个哈希函数从报文文本中生成报文摘要,然后用自己的私人密钥对这个摘要进行加密,这个加密后的摘要将作为报文的”签名“和报文一起发送给接收方,接收方首先用与发送方一样的哈希函数从接收到的原始报文中计算出报文摘要,接着再用发送方的公用密钥来对报文附加的数字签名进行解密,如果这两个摘要相同、那么接收方就能确认报文是从发送方发送且没有被遗漏和修改过!这就是结合“非对称密钥加解密”和“数字摘要“技术所能做的事情,这也就是人们所说的“数字签名”技术。在这个过程中,对传送数据生成摘要并使用私钥进行加密地过程就是生成”数字签名“的过程,经过加密的数字摘要,就是人们所说的”数字签名“!(本段摘自袭烽的博客)附上一张我理解的数字签名的图:

最后 附上使用java来对信息实现数字签名的代码:

package test;import java.io.File;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.IOException;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;import java.security.KeyPair;import java.security.KeyPairGenerator;import java.security.MessageDigest;import java.security.PrivateKey;import java.security.PublicKey;import java.security.Signature;public class Key {/** * 此方法用来生成加密用的公钥和私钥    * 为了保证每次使用的公钥和私钥一致 所以将公钥和私钥保存成为公钥文件和私钥文件 */public void generateKey()throws Exception{FileOutputStream fos_public=new FileOutputStream("d:/public.key");ObjectOutputStream oos_public=new ObjectOutputStream(fos_public);FileOutputStream fos_private=new FileOutputStream("d:/private.key");ObjectOutputStream oos_private =new ObjectOutputStream(fos_private);//KeyPairGenerator 类用于生成公钥和私钥对。密钥对生成器是使用 getInstance 工厂方法(返回一个给定类的实例的静态方法)构造的。 //特定算法的密钥对生成器可以创建能够与此算法一起使用的公钥/私钥对。它还可以将特定于算法的参数与每个生成的密钥关联。 //有两种生成密钥对的方式:与算法无关的方式和特定于算法的方式。两种方式的唯一区别在于对象的初始化//形成DSA公钥对KeyPairGenerator keyGen=KeyPairGenerator.getInstance("DSA");//初始化密钥对生成器,使用指定参数集合.keyGen.initialize(1024);//生成公钥和私钥对//KeyPair类是简单的密钥对(公钥和私钥)持有者。它没有增强任何安全性,。 KeyPair key=keyGen.generateKeyPair();PublicKey publicKey=key.getPublic();PrivateKey privateKey=key.getPrivate();//将生成的公钥对和私钥对写入文件oos_public.writeObject(publicKey);oos_private.writeObject(privateKey);//释放资源fos_public.close();oos_public.close();fos_private.close();oos_private.close();}/** * 对指定的信息的信息出摘要 * @param context 要计算出摘要的信息 * @return  * @throws Exception */public byte[] inThisPaper(String context)throws Exception{MessageDigest alg=MessageDigest.getInstance("MD5");//添加要计算出的摘要信息alg.update(context.getBytes());//计算出摘要return alg.digest();}/** * 对指定的内容进行私钥加密 * @param context 要加密的内容 * @param privateKey  加密的私钥 * @return 加密后的结果 * @throws Exception */public byte[] privateSinature( byte[] context,PrivateKey privateKey)throws Exception{//Signature 类用来为应用程序提供数字签名算法功能//创建爱你指定签名算法的 Signature 对象,需要指定算法。Signature sig=Signature.getInstance("DSA");//设置加密的私钥sig.initSign(privateKey);//设置加密的内容sig.update(context);//返回加密后的信息return sig.sign();} public boolean verify(byte[] context,byte[] verifyContext,PublicKey publicKey)throws Exception{Signature sig=Signature.getInstance("DSA");sig.initVerify(publicKey);sig.update(context);if(sig.verify(verifyContext)){return true;}else{return false;}}/** * 此方法为给文件加上签名 * @param args */public static void main(String[] args) {Key key=new Key();FileInputStream fis_private;try {//读取要签名的文件File file_info=new File("d:/info.txt");FileInputStream fis_info=new FileInputStream(file_info);int fileInfoLength=(int)file_info.length();byte[] infoBytes=new byte[fileInfoLength];fis_info.read(infoBytes);fis_info.close();//读取出私钥fis_private = new FileInputStream("d:/private.key");ObjectInputStream ois_private=new ObjectInputStream(fis_private);PrivateKey privateKey=(PrivateKey)ois_private.readObject();fis_private.close();ois_private.close();//为文件签名 并且发送方应该将两个文件都发送给接收方byte[] sig=key.privateSinature(infoBytes, privateKey);FileOutputStream fos_singnature=new FileOutputStream("d:/sig.sgn");fos_singnature.write(sig);fos_singnature.close();//如果是完整的事例应该是应该将这两个文件打包成一个文件 //然后接收方应该两个文件都有 并且验证后的信息 完全相同才是正确的 //此处因为验证方和接收方是同一个人 所以就不做打包了//并且也不验证两个文件是否都存在了} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();} catch (ClassNotFoundException e) {e.printStackTrace();} catch (Exception e) {e.printStackTrace();}}/** * 此方法为验证签名是否相同 * @param argspublic static void main(String[] args) {try {Key key=new Key();//读取要验证签名的文件File file_info=new File("d:/info.txt");FileInputStream fis_info = new FileInputStream(file_info);int fileInfoLength=(int)file_info.length();byte[] infoBytes=new byte[fileInfoLength];fis_info.read(infoBytes);fis_info.close();//读取出公钥FileInputStreamfis_public = new FileInputStream("d:/public.key");ObjectInputStream ois_public=new ObjectInputStream(fis_public);PublicKey publicKey=(PublicKey)ois_public.readObject();fis_public.close();ois_public.close();//读取出签名文件File file_signature=new File("d:/sig.sgn");FileInputStream fis_signature=new FileInputStream(file_signature);int fileSignatureLength=(int) file_signature.length();byte[]signatureBytes=new byte[fileSignatureLength];fis_signature.read(signatureBytes);fis_signature.close();//验证签名是否相同boolean result=key.verify(infoBytes, signatureBytes, publicKey);if(result){System.out.println("文件没有被篡改");}else{System.out.println("文件被篡改");}} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();} catch (ClassNotFoundException e) {e.printStackTrace();} catch (Exception e) {e.printStackTrace();}} */}

此段代码要想执行成功  在d盘需要有公钥文件和私钥文件 大家可以写个main方法 来调用key类中的generateKey方法 来生成公钥和私钥....