使用数字签名验证文件是否被修改
2013-01-28 22:30
351 查看
基本原理:
发送方:
1. 生成公钥和私钥并保存至文件public.key和private.key。
2. 根据要发送的文件内容生成签名并写入文件signature.dtx。
3. 将公钥文件、签名文件和要发送的文件一起发送给接受方。
接受方:
1. 读取发送方发送的公钥文件
2. 读取发送方发送的签名文件。
3. 读取发送方发送的文件。
4. 根据发送方发送的公钥对发送方发送的文件进行签名。
5. 对比生成的签名和发送方发送的签名是否一致。
代码:
接受方:
1. 运行Sender.java,生成公钥和私钥、签名写入文件。
2. 运行Receiver.java,使用发送方的公钥验证签名。
测试:执行1,生成3个文件:
调试信息:
DEBUG [main] - 已生成私钥文件:private.key,公钥文件:public.key
DEBUG [main] - 根据文件内容生成签名并写入签名文件完毕!
DEBUG [main] - 签名文件写入到signature.dtx
执行2,输出结果:
INFO [main] - 接受方验证文件无篡改!
现在修改文件d:/test.xml,再次执行2,输出结果:
INFO [main] - 接受方验证文件被篡改!
发送方:
1. 生成公钥和私钥并保存至文件public.key和private.key。
2. 根据要发送的文件内容生成签名并写入文件signature.dtx。
3. 将公钥文件、签名文件和要发送的文件一起发送给接受方。
接受方:
1. 读取发送方发送的公钥文件
2. 读取发送方发送的签名文件。
3. 读取发送方发送的文件。
4. 根据发送方发送的公钥对发送方发送的文件进行签名。
5. 对比生成的签名和发送方发送的签名是否一致。
代码:
package com.security.example.example1; 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.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; import org.apache.log4j.Logger; /** * 发送方。 * @author lucky star * */ public class Sender { private static Logger log = Logger.getLogger(Sender.class); public void writeKeysToFiles(String privateFileName,String publicFileName)throws NoSuchAlgorithmException, FileNotFoundException, IOException { KeyPairGenerator keygen = KeyPairGenerator.getInstance("DSA"); keygen.initialize(1024); KeyPair kp = keygen.generateKeyPair(); PrivateKey privateKey = kp.getPrivate(); PublicKey publicKey = kp.getPublic(); ObjectOutputStream out_private = new ObjectOutputStream(new FileOutputStream(privateFileName)); out_private.writeObject(privateKey); out_private.close(); ObjectOutputStream out_public = new ObjectOutputStream(new FileOutputStream(publicFileName)); out_public.writeObject(publicKey); out_public.close(); log.debug("已生成私钥文件:" + privateFileName +",公钥文件:" + publicFileName); } /** * 读取私钥文件得到私钥,并根据文件内容生成签名并写入签名文件。 * @param privateFile:私钥文件。 * @param f:要发送的文件 * @throws FileNotFoundException:如果文件未找到 * @throws IOException:如果出现读写异常 * @throws ClassNotFoundException:如果类未找到 * @throws NoSuchAlgorithmException:如果没有此算法 * @throws InvalidKeyException:如果私钥不可用 * @throws SignatureException:如果签名失败 */ public void send(File privateFile,File sigendFile,File f) throws FileNotFoundException, IOException, ClassNotFoundException, NoSuchAlgorithmException, InvalidKeyException, SignatureException { if (privateFile==null) { thrownew FileNotFoundException("没有找到私钥文件!"); } if (f ==null) { thrownew FileNotFoundException("没有找到要加密的文件!"); } // 读取文件,得到私钥 ObjectInputStream in = new ObjectInputStream(new FileInputStream(privateFile)); PrivateKey privateKey = (PrivateKey) in.readObject(); in.close(); // 根据文件生成签名,并保存到文件signature.dxt byte[] data =new byte[(int) f.length()]; FileInputStream fis = new FileInputStream(f); fis.read(data); fis.close(); Signature sign = Signature.getInstance("DSA"); sign.initSign(privateKey); sign.update(data); // 生成签名 byte[] signedBytes = sign.sign(); // 将签名写入文件 FileOutputStream fos = new FileOutputStream(sigendFile); fos.write(signedBytes,0,signedBytes.length); fos.close(); log.debug("根据文件内容生成签名并写入签名文件完毕!"); log.debug("签名文件写入到" + sigendFile.getName()); } public static void main(String[] args) { // 私钥文件 String privateFileName = "private.key"; // 公钥文件 String publicFileName = "public.key"; // 签名文件 String signedFileName = "signature.dtx"; // 发送方要发送的文件。 File f = new File("d:/test.xml"); File privateFile = new File(privateFileName); File sigendFile = new File(signedFileName); try { Sender sender = new Sender(); // 发送方将公钥和私钥保存到文件private.key和public.key sender.writeKeysToFiles(privateFileName, publicFileName); // 发送方根据文件内容生成签名并写入signature.dtx sender.send(privateFile,sigendFile,f); } catch (NoSuchAlgorithmException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (InvalidKeyException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (SignatureException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (ClassNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } |
接受方:
package com.security.example.example1; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.ObjectInputStream; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.security.PublicKey; import java.security.Signature; import java.security.SignatureException; import org.apache.log4j.Logger; /** * 接受方。 * @author lucky star * */ public class Receiver { private static Logger log = Logger.getLogger(Receiver.class); /** * 接受方读取发送方的公钥文件得到公钥,并以公钥验证签名。 * @param publicKeyFile:公钥文件。 * @param f:发送方发送的文件。 * @return:签名是否验证OK。 * @throws NoSuchAlgorithmException:如果没有此算法。 * @throws FileNotFoundException:如果文件未找到。 * @throws IOException:如果读写异常 * @throws ClassNotFoundException:如果类未找到 * @throws InvalidKeyException:如果公钥不可用 * @throws SignatureException:如果签名失败 */ public boolean receive(File publicKeyFile,File signedFile,File f) throws NoSuchAlgorithmException, FileNotFoundException, IOException, ClassNotFoundException, InvalidKeyException, SignatureException { if (publicKeyFile ==null) { thrownew FileNotFoundException("公钥文件未找到!"); } if (f ==null) { thrownew FileNotFoundException("发送方没有发送文件!"); } // 读取公钥文件得到公钥 ObjectInputStream in = new ObjectInputStream(new FileInputStream(publicKeyFile)); PublicKey pk = (PublicKey) in.readObject(); in.close(); // 读取发送方发送的文件,读入字节数组 byte[] data =new byte[(int) f.length()]; FileInputStream fis = new FileInputStream(f); fis.read(data); // 读取发送方的签名文件 byte[] signData =new byte[(int) signedFile.length()]; FileInputStream fis2 = new FileInputStream(signedFile); fis2.read(signData); fis2.close(); // 使用发送方的公钥验证签名 Signature sign = Signature.getInstance("DSA"); sign.initVerify(pk); sign.update(data); return sign.verify(signData); } public static void main(String[] args) { // 公钥文件 String publicFileName = "public.key"; // 签名文件 String signedFileName = "signature.dtx"; // 发送方发送的文件。 File f = new File("d:/test.xml"); File publicFile = new File(publicFileName); File sigendFile = new File(signedFileName); try { Receiver recv = new Receiver(); // 接受方读取发送方提供的公钥文件验证签名是否一致 boolean isOk = recv.receive(publicFile,sigendFile, f); if (isOk) { log.info("接受方验证文件无篡改!"); } else { log.info("接受方验证文件被篡改!"); } } catch (NoSuchAlgorithmException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (InvalidKeyException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (SignatureException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (ClassNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } |
1. 运行Sender.java,生成公钥和私钥、签名写入文件。
2. 运行Receiver.java,使用发送方的公钥验证签名。
测试:执行1,生成3个文件:
调试信息:
DEBUG [main] - 已生成私钥文件:private.key,公钥文件:public.key
DEBUG [main] - 根据文件内容生成签名并写入签名文件完毕!
DEBUG [main] - 签名文件写入到signature.dtx
执行2,输出结果:
INFO [main] - 接受方验证文件无篡改!
现在修改文件d:/test.xml,再次执行2,输出结果:
INFO [main] - 接受方验证文件被篡改!
相关文章推荐
- Windows证书的生成导出以及使用证书验证文件是否被修改
- C# 使用xsd文件验证XML 格式是否正确
- python 使用SAX解析器验证xml文件格式是否完好
- 使用signtool.exe来验证程序的数字签名是否成功(命令行)
- C#使用xsd文件验证XML格式是否正确的实现方法
- C# 使用xsd文件验证XML 格式是否正确
- 怎样使用.sig文件生成/验证数字签名?
- Linux下使用md5sum查看文件及程序是否被修改
- C#使用xsd文件验证XML 格式是否正确
- [Android]使用checksum校验文件是否被修改
- 使用gpg进行安全签名来验证下载的文件是否完整
- 利用OpenSSL生成的私钥、公钥和证书,用来验证文件是否被修改
- 使用配制文件定制身份验证和基于角色的安全
- 使用ant剪切、重命名、修改文件访问时间
- Windows系统让apache使用其他名称的配置文件修改配置文件名称指定自己的配置文件
- 使用System.IO来读取以及修改文本文件
- 使用golang获取linux上文件的访问/创建/修改时间
- 使用BBED修改SCN让数据文件online
- Java与邮件系统交互之使用Socket验证邮箱是否存在
- [libxml2]_[XML处理]_[使用libxml2的xpath特性修改xml文件内容]