转载:文件数字签名zxc

该博客展示了使用Java实现文件签名与验证的代码。发送方通过DSA算法生成公私钥并保存到文件,根据文件内容生成签名并写入签名文件;接收方读取公钥文件,以公钥验证签名,判断文件是否被篡改,保障了文件传输的安全性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

package com.ccc.signature;

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;

public class Sender {
    
    /**
     * 
     * @param privateFileName : 私钥文件名
     * @param publicFileName : 公钥文件名
     * @throws NoSuchAlgorithmException : 算法没找到
     * @throws FileNotFoundException : 文件没找到
     * @throws IOException : 读写异常
     */
    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();

        System.out.println("已生成私钥文件:" + 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) {
            throw new FileNotFoundException("没有找到私钥文件!");
        }
        if (f == null) {
            throw new 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();

        System.out.println("根据文件内容生成签名并写入签名文件完毕!");
        System.out.println("签名文件写入到" + sigendFile.getName());
    }

    public static void main(String[] args) {
        System.out.println("----");
        // 私钥文件
        String privateFileName = "private.key";
        // 公钥文件
        String publicFileName = "public.key";
        // 签名文件
        String signedFileName = "signature.dtx";
        // 发送方要发送的文件。
        File f = new File("D:\\test\\apache-maven-3.6.3-bin.zip");
        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) {
            e.printStackTrace();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        } catch (SignatureException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

}
 

 

 

package com.ccc.signature;

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;

public class Receiver {
    
    /**
     * 接受方读取发送方的公钥文件得到公钥,并以公钥验证签名。
     * @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) {
            throw new FileNotFoundException("公钥文件未找到!");
        }
        if (f == null) {
            throw new 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);
        fis.close();
        return sign.verify(signData);
    }
    
    public static void main(String[] args) {
        // 公钥文件
        String publicFileName = "public.key";
        // 签名文件
        String signedFileName = "signature.dtx";
        // 发送方发送的文件。
        File f = new File("/Users/ice/Downloads/file_check_test.txt");
        File publicFile = new File(publicFileName);
        File sigendFile = new File(signedFileName);
        
        try {
            Receiver recv = new Receiver();
            // 接受方读取发送方提供的公钥文件验证签名是否一致
            boolean isOk = recv.receive(publicFile,sigendFile, f);
            if (isOk) {
                System.out.println("接受方验证文件无篡改!");
            } else {
                System.out.println("接受方验证文件被篡改!");
            }
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        } catch (SignatureException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

}
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值