`

使用数字签名验证文件是否被修改

阅读更多

基本原理:

发送方:

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.keypublic.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] - 接受方验证文件被篡改!

分享到:
评论

相关推荐

    验证文件的微软数字签名源码

    本篇将详细介绍如何验证文件的微软数字签名,并分享使用VC6.0实现的相关源码。 首先,理解数字签名的概念至关重要。数字签名并非字面上的签名,而是一种加密技术,用于验证文件的完整性和发送者的身份。它利用非...

    数字签名日期修改器——修改文件过期时间

    在Office文件中,例如PDF或DOCX文档,数字签名用于验证文档自签署以来没有被修改过,这对于法律文档、合同等至关重要。在EXE文件中,数字签名则有助于防止恶意软件,因为用户可以看到软件发布者的身份,并确认文件在...

    数字签名文件,数字签名文件

    在软件发布中,数字签名能够确保用户下载的软件是由可信的开发者发布的,没有被恶意修改过。因此,数字签名广泛应用于软件发行、电子邮件验证、重要文档签署等场景中,成为不可或缺的安全保障措施。 然而,正如给定...

    给CAB文件加上数字签名

    通过数字签名,用户可以确认控件的发布者身份,并验证文件自签名以来是否被修改过。 #### 三、数字签名的基本原理 数字签名涉及到公钥加密技术。当一个文件被数字签名时,会使用签名者的私钥来创建一个数字签名,...

    数字签名验证工具(查病毒辅助工具)

    在本文中,我们将深入探讨数字签名的概念、工作原理以及如何使用数字签名验证工具来确保软件的安全性。 首先,让我们了解什么是数字签名。数字签名并非是我们在日常生活中手写的签名,而是一种基于公钥加密技术的...

    用API验证数字签名

    在这个场景中,我们要使用API来验证数字签名,这是一个关键的安全功能,可以确保我们正在执行或处理的代码或文件未被恶意修改。 API(应用程序接口)是一组预定义的函数、类和对象,允许开发者通过调用这些接口来...

    ,易语言软件的数字签名

    描述中提到的"减少杀毒软件的误报",这是因为许多杀毒软件会检查软件的数字签名来判断其是否来自可信赖的来源,如果一个软件有有效的数字签名,那么被误识别为病毒的可能性就会大大降低。这对于易语言编写的软件来说...

    jsp数字签名系统

    在数字签名系统中,通常包括三个主要步骤:签名生成、数据传输和签名验证。签名生成是使用发送者的私钥对数据进行加密,而验证则是使用发送者的公钥对签名进行解密。如果解密后的数据与原始数据匹配,那么签名就是...

    EXE资源修改器--修改文件内容文件签名等等 强大

    数字签名包含开发者的信息和对文件内容的哈希,验证时会检查哈希是否与原始文件匹配。 5.逆向工程:逆向工程是分析软件的工作原理,通常用于安全审计、学习代码技术或调试。资源修改器有时被逆向工程师用来辅助分析...

    数字签名验证(MD5工具)

    MD5验证工具非常实用的一款小软件!MD5是message-digest algorithm 5(信息-摘要算法)的缩写,被广泛用于加密和解密技术上,它可以说是...因此,我们可以通过对比同一文件的MD5值,来校验这个文件是否被“篡改”过。

    57.PE文件逆向之什么是数字签名及Signtool签名工具详解(一)1

    在PE(Portable Executable)文件中,如Windows上的.exe和.dll文件,数字签名用于验证程序的合法性,防止用户运行被恶意修改的代码。 一、PE文件的数字签名 1. **签名目的**:数字签名的主要目标是提供代码完整性...

    易语言软件验证自身是否被修改

    综上所述,易语言软件验证自身是否被修改的策略包括但不限于数字签名、哈希校验、反调试、代码混淆和资源校验等,这些方法组合使用可以显著提高软件的安全性,防止恶意篡改。在实际应用中,开发者需要根据具体需求和...

    数字签名添加器 数字签名添加器

    2. **完整性检查**:数字签名可以检测文件是否自签名后被篡改过。一旦文件内容发生任何改变,签名将无效,从而保护接收者免受恶意修改的影响。 3. **非否认性**:由于数字签名与发送者的私钥绑定,签名后无法否认其...

    数字签名克隆工具

    当开发者为他们的软件添加数字签名时,用户可以通过检查签名来确认软件是由可信的源创建的,并且没有在分发过程中被修改。 然而,"数字签名克隆工具"是指能够复制或模仿已有的合法数字签名的软件。这类工具可能被...

    数字签名添加器 下载

    数字签名添加器是一款专门用于为文件添加数字签名的工具,能够帮助用户确保他们分发的文件不被篡改,并且可以避免某些防病毒软件的误报,从而实现文件的“免杀”效果。 首先,我们要理解什么是数字签名。在计算机...

    代码签名数字证书(含私钥)_过期证书_过期数字签名强制签名工具_数字签名_证书

    在描述中提到“成品exe,若容查杀没毒”,这暗示了开发者可能在确保软件安全无毒后,使用这样的工具来确保软件能够正常运行,尽管其数字签名已经过期。 “数字签名”是一个关键的概念,它是通过哈希算法和非对称...

    XP数字签名工具用于数字签名

    4. **验证**:接收者使用签名者的公钥对嵌入的数字签名进行解密,然后再次计算文件的哈希值。如果两者匹配,则证明文件未被篡改,且发送者身份可确认。 在Windows XP中,数字签名对于驱动程序尤其重要,因为系统会...

    对pdf文档进行数字签名

    4. **验证**:接收者可以使用签名者的公钥和嵌入的证书来解密数字签名,对比解密后的哈希值与当前文档的哈希值,确认文档是否被修改。 在ITeye博客中,链接提到的可能是一篇关于如何实现或使用工具进行PDF数字签名...

Global site tag (gtag.js) - Google Analytics