RSA加密验签

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import javax.crypto.Cipher;

import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

public class Sha1withRSAUtil {
    /**
     * 指定加密算法为RSA
     */
    private static String ALGORITHM = "RSA";
    /**
     * 指定Key的大小
     */
    private static int KEY_SIZE = 1024;
    /**
     * 指定公钥存放文件
     */
    private static String PUBLIC_KEY_FILE = "d:/PublicKey";
    /**
     * 指定私钥存放文件
     */
    private static String PRIVATE_KEY_FILE = "d:/PrivateKey";

    /**
     * 解析后的公钥
     */
    private static String PUBLIC_KEY = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCmozQDA1Yn8lhqZkAsD9mXoJ99R9wS1/5LW9E7" +
            "WZt1tFTbLUhkzz3G26KzGY9OYPrRyLBeXG0w/WLRwI+uMEFC2W9quCxf98DsE8SBZ4s74wn/5ElO" +
            "1rJRAaAu1VDTyY0dcAMHIgBedWMWRgrM037eZJsLXZb8qBRbSQt27LoJFwIDAQAB";
    /**
     * 解析后的私钥
     */
    private static String PRIVATE_KEY = "MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAKajNAMDVifyWGpmQCwP2Zegn31H" +
            "3BLX/ktb0TtZm3W0VNstSGTPPcbborMZj05g+tHIsF5cbTD9YtHAj64wQULZb2q4LF/3wOwTxIFn" +
            "izvjCf/kSU7WslEBoC7VUNPJjR1wAwciAF51YxZGCszTft5kmwtdlvyoFFtJC3bsugkXAgMBAAEC" +
            "gYAU6cygSC3q64ZfLCAHp6GWXwlFLtyW3NbEXGyg9zkEh7JSo5c/V6cYKv57XczXeGJiK76+yPjH" +
            "OjXJv1II+XNnHXvN0urZ5SDQr2erk4xslXsun6X3sMqgcyU19xBnJEzhfApl2MFMyPrw/a6sStDg" +
            "EWK6rRfxdLVxeQ/TBDu4SQJBANlQl5BSvA7g/l8m6lQSq+1j9pa1QBIW8s7KYLB4C+WlYBUa/5mD" +
            "fggTH4UKihWjaBbPVlj49YKTD205s8zBujUCQQDETSjppGRSnTQCWpRUjXFd9Fe2E5CQrmCqHYNP" +
            "0YW6gj+9E7tdz7auH1EmyfrsAobyi27OcPE+3/DNrfdpln+bAkEAsBdnCTKRYnkchhvxi3ipyi3T" +
            "VeG+7imcTMaevMA527c6+T8sWMe9K2vbgaG9rLUBlmIh9OyffFQQDxDPyh489QJBAKkAoTOeE71I" +
            "mKlaIJA3Ah5YqlcYuwLFDnYHWLEUeySa1JNNdKeMmAOK9MwHYt9kQZh50NktRZXTKTd7CiI+rvcC" +
            "QAQcZkQQqsE4xoZPocDdWFP9eG0dPONq9NOemfNe+IxNLE52zumwzsMeoX7OgzyZwkhSnJyhluP2" +
            "u0I2p0u3tVQ=";
    public static final String KEY_ALGORITHM = "RSA";

    public static final String SIGNATURE_ALGORITHM = "SHA1withRSA";

    /**
     * 生成密钥对
     */
    public static void generateKeyPair() throws Exception {
        if (getPublicKey() == null || getPrivateKey() == null) {
            /** RSA算法要求有一个可信任的随机数源 */
            SecureRandom sr = new SecureRandom();
            /** 为RSA算法创建一个KeyPairGenerator对象 */
            KeyPairGenerator kpg = KeyPairGenerator.getInstance(ALGORITHM);
            /** 利用上面的随机数据源初始化这个KeyPairGenerator对象 */
            kpg.initialize(KEY_SIZE, sr);
            /** 生成密匙对 */
            KeyPair kp = kpg.generateKeyPair();
            /** 得到公钥 */
            Key publicKey = kp.getPublic();
            /** 得到私钥 */
            Key privateKey = kp.getPrivate();
            /** 用对象流将生成的密钥写入文件 */
            ObjectOutputStream oos1 = new ObjectOutputStream(new FileOutputStream(PUBLIC_KEY_FILE));
            ObjectOutputStream oos2 = new ObjectOutputStream(new FileOutputStream(PRIVATE_KEY_FILE));
            oos1.writeObject(publicKey);
            oos2.writeObject(privateKey);
            /** 清空缓存,关闭文件输出流 */
            oos1.close();
            oos2.close();
        }

    }

    /**
     * 产生签名
     *
     * @param data
     * @param privateKey
     * @return
     * @throws Exception
     */
    public static String sign(byte[] data, String privateKey) throws Exception {
        // 解密由base64编码的私钥
        byte[] keyBytes = decryptBASE64(privateKey);

        // 构造PKCS8EncodedKeySpec对象
        PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);

        // KEY_ALGORITHM 指定的加密算法
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);

        // 取私钥对象
        PrivateKey priKey = keyFactory.generatePrivate(pkcs8KeySpec);

        // 用私钥对信息生成数字签名
        Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
        signature.initSign(priKey);
        signature.update(data);

        return encryptBASE64(signature.sign());
    }

    /**
     * 验证签名
     *
     * @param signString
     * @param sign
     * @return
     * @throws Exception
     */
    public static boolean verify(String signString, String sign) throws Exception {

        byte[] data = decryptBASE64(signString);

        byte[] signs = sign.getBytes();

        try {
            // 实例化
            Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
            // 解密由base64编码的公钥
            byte[] keyBytes = decryptBASE64(PUBLIC_KEY);

            // 构造X509EncodedKeySpec对象
            X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);

            // KEY_ALGORITHM 指定的加密算法
            KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);

            // 取公钥对象
            PublicKey pubKey = keyFactory.generatePublic(keySpec);
            // 初始化
            signature.initVerify(pubKey);

            // 更新
            signature.update(signs);

            // 验签
            return signature.verify(data);

        } catch (NoSuchAlgorithmException | InvalidKeyException | SignatureException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        return false;
    }

    /**
     * BASE64解密
     *
     * @param key
     * @return
     * @throws Exception
     */
    public static byte[] decryptBASE64(String key) throws Exception {
        return (new BASE64Decoder()).decodeBuffer(key);
    }

    /**
     * BASE64加密
     *
     * @param key
     * @return
     * @throws Exception
     */
    public static String encryptBASE64(byte[] key) throws Exception {
        return (new BASE64Encoder()).encodeBuffer(key);
    }

    /**
     * 加密方法 source: 源数据
     */
    public static String encrypt(String source) throws Exception {
        /** 将文件中的公钥对象读出 */
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream(PUBLIC_KEY_FILE));
        Key key = (Key) ois.readObject();
        ois.close();
        /** 得到Cipher对象来实现对源数据的RSA加密 */
        Cipher cipher = Cipher.getInstance(ALGORITHM);
        cipher.init(Cipher.ENCRYPT_MODE, key);
        int MaxBlockSize = KEY_SIZE / 8;
        int len = (MaxBlockSize - 11) / 8;
        String[] result = splitString(source, len);
        StringBuffer sb = new StringBuffer();
        for (String s : result) {
            sb.append(bcd2Str(cipher.doFinal(s.getBytes())));
        }
        return sb.toString();

    }

    /**
     * 字符串分片
     *
     * @param string 源字符串
     * @param len    单片的长度(keySize/8)
     * @return
     */
    public static String[] splitString(String string, int len) {
        int x = string.length() / len;
        int y = string.length() % len;
        int z = 0;
        if (y != 0) {
            z = 1;
        }
        String[] strings = new String[x + z];
        String str = "";
        for (int i = 0; i < x + z; i++) {
            if (i == x + z - 1 && y != 0) {
                str = string.substring(i * len, i * len + y);
            } else {
                str = string.substring(i * len, i * len + len);
            }
            strings[i] = str;
        }
        return strings;
    }

    /**
     * bcd 转 Str
     *
     * @param bytes
     * @return
     */
    public static String bcd2Str(byte[] bytes) {
        char temp[] = new char[bytes.length * 2], val;
        for (int i = 0; i < bytes.length; i++) {
            val = (char) (((bytes[i] & 0xf0) >> 4) & 0x0f);
            temp[i * 2] = (char) (val > 9 ? val + 'A' - 10 : val + '0');

            val = (char) (bytes[i] & 0x0f);
            temp[i * 2 + 1] = (char) (val > 9 ? val + 'A' - 10 : val + '0');
        }
        return new String(temp);
    }

    /**
     * 解密
     *
     * @param cryptoGraph :密文
     * @return 解密后的明文
     * @throws Exception
     */
    public static String decrypt(String cryptoGraph) throws Exception {
        /** 将文件中的私钥对象读出 */
        @SuppressWarnings("resource")
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream(PRIVATE_KEY_FILE));
        Key key = (Key) ois.readObject();
        /** 得到Cipher对象对已用公钥加密的数据进行RSA解密 */
        Cipher cipher = Cipher.getInstance(ALGORITHM);
        cipher.init(Cipher.DECRYPT_MODE, key);
        int key_len = KEY_SIZE / 8;
        byte[] bytes = cryptoGraph.getBytes();
        byte[] bcd = ASCII2BCD(bytes, bytes.length);
        StringBuffer sBuffer = new StringBuffer();
        byte[][] arrays = splitArray(bcd, key_len);
        for (byte[] arr : arrays) {
            sBuffer.append(new String(cipher.doFinal(arr)));
        }
        return sBuffer.toString();
    }

    /**
     * ASCII 转 BCD
     *
     * @param ascii
     * @param asc_len
     * @return
     */
    public static byte[] ASCII2BCD(byte[] ascii, int asc_len) {
        byte[] bcd = new byte[asc_len / 2];
        int j = 0;
        for (int i = 0; i < (asc_len + 1) / 2; i++) {
            bcd[i] = asc2bcd(ascii[j++]);
            bcd[i] = (byte) (((j >= asc_len) ? 0x00 : asc2bcd(ascii[j++])) + (bcd[i] << 4));
        }
        return bcd;
    }

    /**
     * asc转bcd
     *
     * @param asc
     * @return
     */
    public static byte asc2bcd(byte asc) {
        byte bcd;

        if ((asc >= '0') && (asc <= '9'))
            bcd = (byte) (asc - '0');
        else if ((asc >= 'A') && (asc <= 'F'))
            bcd = (byte) (asc - 'A' + 10);
        else if ((asc >= 'a') && (asc <= 'f'))
            bcd = (byte) (asc - 'a' + 10);
        else
            bcd = (byte) (asc - 48);
        return bcd;
    }

    /**
     * 字节数组分片
     *
     * @param data
     * @param len
     * @return
     */
    public static byte[][] splitArray(byte[] data, int len) {
        int x = data.length / len;
        int y = data.length % len;
        int z = 0;
        if (y != 0) {
            z = 1;
        }
        byte[][] arrays = new byte[x + z][];
        byte[] arr;
        for (int i = 0; i < x + z; i++) {
            arr = new byte[len];
            if (i == x + z - 1 && y != 0) {
                System.arraycopy(data, i * len, arr, 0, y);
            } else {
                System.arraycopy(data, i * len, arr, 0, len);
            }
            arrays[i] = arr;
        }
        return arrays;
    }

    /**
     * 将文件中的公钥对象读出
     */
    public static String getPublicKey() {

        try {
            ObjectInputStream ois = new ObjectInputStream(new FileInputStream(PUBLIC_KEY_FILE));
            Key key = (Key) ois.readObject();
            String publicKey = encryptBASE64(key.getEncoded());
            return publicKey;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 将文件中的私钥对象读出
     */
    public static String getPrivateKey() {
        try {
            ObjectInputStream ois = new ObjectInputStream(new FileInputStream(PRIVATE_KEY_FILE));
            Key key = (Key) ois.readObject();
            String privateKey = encryptBASE64(key.getEncoded());
            return privateKey;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 验签
     */
    public static void main(String[] args) {
        try {
            // 生成密钥对
            generateKeyPair();
            // 获取公私钥
            String publicKey = getPublicKey();
            String privateKey = getPrivateKey();
            System.out.println("publicKey:" + publicKey);
            System.out.println("privateKey:" + privateKey);

            // 生签
            String signName = "954329";
            byte[] data = signName.getBytes();
            System.out.println(data);
            String sign = sign(data, getPrivateKey());
            System.out.println("sign:" + sign);

            // 验签
            boolean verify = verify(sign, signName);
            System.out.println(verify);

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值