欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

对内容进行签名的实例

程序员文章站 2022-07-04 14:06:40
...
package com.yonge.messagedigest;

import java.io.File;
import java.io.FileInputStream;
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.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.SignatureException;

import org.apache.commons.codec.binary.Base64;

public class SignUtil {

    //加密算法
    private final static String SIGNATURE_ALGORITHM      = "DSA";

    private final static String MESSAGE_DIGEST_ALGORITHM = "MD5";

    private final static String PRIVATE_KEY_FILE_NAME    = "private.key";

    private final static String PUBLIC_KEY_FILE_NAME     = "public.key";

    private static Signature    signature                = null;

    static {
        try {
            //获取签名对象
            signature = Signature.getInstance(SIGNATURE_ALGORITHM);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }

    }

    /**
     * 利用DSA获取摘要,然后用base64进行编码
     * @param file 源文件
     * @return 返回摘要
     * @throws NoSuchAlgorithmException
     * @throws IOException
     */
    public static String getMessageDigest(File file) throws NoSuchAlgorithmException, IOException {
        MessageDigest messageDigest = null;
        FileInputStream fis = null;
        messageDigest = MessageDigest.getInstance(MESSAGE_DIGEST_ALGORITHM);
        byte[] buffer = new byte[1024];
        int length;
        fis = new FileInputStream(file);
        while ((length = fis.read(buffer)) > 0) {
            messageDigest.update(buffer, 0, length);
        }
        //将摘要进行base64编码
        return new String(Base64.encodeBase64(messageDigest.digest()));
    }

    /**
     * 利用DSA获取摘要,然后用base64进行编码
     * @param data
     * @return
     * @throws NoSuchAlgorithmException
     */
    public static String getMessageDigest(byte[] data) throws NoSuchAlgorithmException {
        MessageDigest messageDigest = MessageDigest.getInstance(MESSAGE_DIGEST_ALGORITHM);
        messageDigest.update(data);
        return new String(Base64.encodeBase64(messageDigest.digest()));
    }

    /**
     * 生成密钥对,并保存到文件中(公钥保存到public.key,私钥保存到private.key)
     * @return 是否生成成功
     * @throws NoSuchAlgorithmException
     * @throws IOException 
     */
    public static boolean generateKeyPair() throws NoSuchAlgorithmException, IOException {
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(SIGNATURE_ALGORITHM);
        //生成公钥、私钥对
        KeyPair keyPair = keyPairGenerator.genKeyPair();

        //获取私钥
        PrivateKey privateKey = keyPair.getPrivate();

        //获取公钥
        PublicKey publicKey = keyPair.getPublic();

        //将公钥、私钥保存到本地文件中
        FileOutputStream fos_private = new FileOutputStream(new File(PRIVATE_KEY_FILE_NAME));
        ObjectOutputStream oos_private = new ObjectOutputStream(fos_private);
        oos_private.writeObject(privateKey);
        fos_private.close();
        oos_private.close();

        FileOutputStream fos_public = new FileOutputStream(new File(PUBLIC_KEY_FILE_NAME));
        ObjectOutputStream oos_public = new ObjectOutputStream(fos_public);
        oos_public.writeObject(publicKey);
        fos_public.close();
        oos_public.close();
        return true;
    }

    /**
     * 根据私钥将数据生成签名
     * @param data
     * @return 返回加密后的字节数组
     * @throws IOException 
     * @throws ClassNotFoundException 
     * @throws InvalidKeyException 
     * @throws SignatureException 
     */
    public static byte[] signByPrivateKey(byte[] data) throws IOException, ClassNotFoundException,
                                                      InvalidKeyException, SignatureException {
        PrivateKey privateKey = getPrivateKey();

        //初始化签名对象
        signature.initSign(privateKey);
        //签名操作
        signature.update(data);
        //将签名结果返回到数组中
        return signature.sign();
    }

    /**
     * 验证签名
     * @param data 
     * @param sign 签名
     * @return
     * @throws IOException
     * @throws ClassNotFoundException
     * @throws InvalidKeyException
     * @throws SignatureException
     */
    public static boolean verifyByPublicKey(byte[] data, byte[] sign) throws IOException,
                                                                     ClassNotFoundException,
                                                                     InvalidKeyException,
                                                                     SignatureException {
        PublicKey publicKey = getPublicKey();
        signature.initVerify(publicKey);
        signature.update(data);
        return signature.verify(sign);
    }

    /**
     * 获取私钥对象
     * @return
     * @throws IOException
     * @throws ClassNotFoundException
     */
    public static PrivateKey getPrivateKey() throws IOException, ClassNotFoundException {
        FileInputStream fis = null;
        ObjectInputStream ois = null;
        PrivateKey privateKey = null;
        try {
            //加载私钥文件
            fis = new FileInputStream(new File(PRIVATE_KEY_FILE_NAME));
            ois = new ObjectInputStream(fis);
            //读取对象
            privateKey = (PrivateKey) ois.readObject();
        } finally {
            //关闭流
            if (fis != null) {
                fis.close();
            }
            if (ois != null) {
                ois.close();
            }
        }
        return privateKey;
    }

    /**
     * 获取公钥对象
     * @return
     * @throws IOException
     * @throws ClassNotFoundException
     */
    public static PublicKey getPublicKey() throws IOException, ClassNotFoundException {

        FileInputStream fis = null;
        ObjectInputStream ois = null;
        PublicKey publicKey = null;
        try {
            //加载公钥文件
            fis = new FileInputStream(new File(PUBLIC_KEY_FILE_NAME));
            ois = new ObjectInputStream(fis);
            //读取对象
            publicKey = (PublicKey) ois.readObject();
        } finally {
            //关闭流
            if (fis != null) {
                fis.close();
            }
            if (ois != null) {
                ois.close();
            }
        }
        return publicKey;
    }
}