Java实现文件添加数字签名、验证数字签名

Linux下实现加签、验签

1.使用OpenSSL 生成公钥和密钥;

#用 OpenSSL, Linux 上自带,常用命令如下:
#生成 RSA 私钥(传统格式的)
#用 OpenSSL, Linux 上自带,常用命令如下:
#生成 RSA 私钥(传统格式的)
openssl genrsa -out rsa_private_key.pem 1024
#将传统格式的私钥转换成 PKCS#8 格式的(JAVA需要使用的私钥需要经过PKCS#8编码,PHP程序不需要,可以直接略过)
openssl pkcs8 -topk8 -inform PEM -in rsa_private_key.pem -outform PEM -nocrypt
#生成 RSA 公钥
openssl rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem

2.使用私钥对文件进行加签、并验证

#有明文文件file.txt和RSA密钥rsa_private_key.pem
#使用md5指令指定sha1算法,对file.txt进行签名,生成签名文件sign1.txt
openssl md5 -sha512 -sign rsa_private_key.pem -out data_xinbao.tar.gz.sign data_xinbao.tar.gz
#使用md5指令指定sha1算法,对file.txt进行签名,生成签名文件sign1.txt
openssl dgst -sha512 -sign rsa_private_key.pem -out data_xinbao.tar.gz.sign data_xinbao.tar.gz
#两个签名文件一样,说明两个指令完成相同的功能
diff data_xinbao.tar.gz.sign data_xinbao1.tar.gz.sign
#使用RSA公钥验证签名(verify参数),验证成功
openssl md5 -verify rsa_public_key.pem -sha512 -signature data_xinbao1.tar.gz.sign data_xinbao.tar.gz
openssl dgst -verify rsa_public_key.pem -sha512 -signature data_xinbao.tar.gz.sign data_xinbao.tar.gz

3.查看OpenSSL和帮助

#通过下面命令可以查看openssl的参数说明
$ openssl dgst -
options are
-c              to output the digest with separating colons
-r              to output the digest in coreutils format
-d              to output debug info
-hex            output as hex dump
-binary         output in binary form
-sign   file    sign digest using private key in file
-verify file    verify a signature using public key in file
-prverify file  verify a signature using private key in file
-keyform arg    key file format (PEM or ENGINE)
-out filename   output to filename rather than stdout
-signature file signature to verify
-sigopt nm:v    signature parameter
-hmac key       create hashed MAC with key
-mac algorithm  create MAC (not neccessarily HMAC)
-macopt nm:v    MAC algorithm parameters or key
-engine e       use engine e, possibly a hardware device.
-md4            to use the md4 message digest algorithm
-md5            to use the md5 message digest algorithm
-ripemd160      to use the ripemd160 message digest algorithm
-sha            to use the sha message digest algorithm
-sha1           to use the sha1 message digest algorithm
-sha224         to use the sha224 message digest algorithm
-sha256         to use the sha256 message digest algorithm
-sha384         to use the sha384 message digest algorithm
-sha512         to use the sha512 message digest algorithm
-whirlpool      to use the whirlpool message digest algorithm

4.拿加签的原文件和加签后的文件使用Java代码进行对比;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import java.io.*;
import java.security.*;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Date;

/**
 * 对文件加签、验签工具类
 * 生成私钥:openssl genrsa -out rsa_private_key.pem 1024
 * 私钥还不能直接被使用,需要进行PKCS#8编码:openssl pkcs8 -topk8 -inform PEM -in rsa_private_key.pem -outform PEM -nocrypt
 * 根据私钥生成公钥:openssl rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem
 * 使用私钥sha512签名:openssl dgst -sha512 -sign rsa_private_key.pem -out xx.tar.gz.sign xx.tar.gz
 * 使用公钥sha512验签:openssl dgst -verify rsa_public_key.pem -sha512 -signature xx.tar.gz.sign xx.tar.gz
 * @author XIHONGLIE
 * @date 2018-03-27
 */
public class RsaEncrypt {
   
    /**
     * rsa签名
     * @param data  待签名的字符串
     * @param priKey  rsa私钥字符串
     * @return 签名结果
     * @throws Exception    签名失败则抛出异常
     */
    public byte[] rsaSign(byte[] data, RSAPrivateKey priKey)
            throws SignatureException {
   
        try {
   
            Signature signature = Signature.getInstance("SHA512withRSA");
            signature.initSign(priKey);
            signature.update(data);

            byte[] signed = signature.sign();
            return signed;
        } catch (Exception e) {
   
            throw new SignatureException("RSAcontent = " + data
                    + "; charset = ", e);
        }
    }

    /**
     * rsa验签
     * @param data  被签名的内容
     * @param sign   签名后的结果
     * @param pubKey   rsa公钥
     * @return 验签结果
     * @throws SignatureException 验签失败,则抛异常
     */
    public boolean verify(byte[] data, byte[] sign, RSAPublicKey pubKey)
            throws SignatureException {
   
        try {
   
            Signature signature = Signature.getInstance("SHA512withRSA");
            signature.initVerify(pubKey);
            signature.update(data);
            return signature.verify(sign);

        } catch (Exception e) {
   
            e.printStackTrace();
            throw new SignatureException("RSA验证签名[content = " + data
                    + "; charset = " + "; signature = " + sign + "]发生异常!", e);
        }
    }

    /**
     * 私钥
     */
    private RSAPrivateKey privateKey;

    /**
     * 公钥
     */
    private RSAPublicKey publicKey;

    /**
     * 字节数据转字符串专用集合
     */
    private static final char[] HEX_CHAR = {
    '0', '1', '2', '3', '4', '5', '6',
            '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };

    /**
     * 获取私钥
     * @return 当前的私钥对象
     */
    public RSAPrivateKey getPrivateKey() {
   
        return privateKey;
    }

    /**
     * 获取公钥
     * @return 当前的公钥对象
     */
    public RSAPublicKey getPublicKey() {
   
        return publicKey;
    }

    /**
     * 随机生成密钥对
     */
    public void genKeyPair() {
   
        KeyPairGenerator keyPairGen = null;
        try {
   
            keyPairGen = KeyPairGenerator.getInstance("RSA");
        } catch (NoSuchAlgorithmException e) {
   
            e.printStackTrace();
        }
        keyPairGen.initialize(1024, new SecureRandom());
        KeyPair keyPair = keyPairGen.generateKeyPair();
        this.privateKey = (RSAPrivateKey) keyPair.getPrivate();
        this.publicKey = (RSAPublicKey) keyPair.getPublic();
    }

    /**
     * 从.pem文件中取得私钥
     * @param filePath 文件路径
     * @return 私钥
     */
    public String getPrivateKeyFromFile(String filePath){
   
        String strPrivateKey = "";
        try {
   
            BufferedReader privateKey = new BufferedReader(new FileReader(filePath));
            String line = "";
            while((line = privateKey.readLine()) != null){
   
                strPrivateKey += line;
            }
            privateKey.close();
            strPrivateKey = strPrivateKey.replace("-----BEGIN PRIVATE KEY-----","").replace("-----END PRIVATE KEY-----","");
        }catch (Exception e){
   
            e.printStackTrace();
        }
        return strPrivateKey;
    }

    /**
     * 从.pem文件中取得公钥
     * @param filePath 文件路径
     * @return 公钥
     */
    public String getPublicKeyFromFile(String filePath){
   
        String strPublicKey = "";
        try {
   
            BufferedReader publicKey = new BufferedReader(new FileReader(filePath));
            String line = "";
            while((line = publicKey.readLine()) != null){
   
                strPublicKey += line;
            }
            publicKey.
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值