RSA密钥生成、加密解密、数据签名验签

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/lupengfei1009/article/details/78199329

公钥、私钥生成

准备工作,基础的帮助类

  • base64的数据帮助类
    代码依赖jar包javabase64-1.3.1.jar

    import java.io.ByteArrayInputStream;
    import java.io.ByteArrayOutputStream;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.InputStream;
    import java.io.OutputStream;
    
    import it.sauronsoftware.base64.Base64;
    
    /** */
    /**
     * <p>
     * BASE64编码解码工具包
     * </p>
     * <p>
     * 依赖javabase64-1.3.1.jar
     * </p>
     * 
     */
    public class Base64Utils
    {
    
        /** */
        /**
         * 文件读取缓冲区大小
         */
        private static final int CACHE_SIZE = 1024;
    
        /** */
        /**
         * <p>
         * BASE64字符串解码为二进制数据
         * </p>
         * 
         * @param base64
         * @return
         * @throws Exception
         */
        public static byte[] decode(String base64) throws Exception
        {
            return Base64.decode(base64.getBytes());
        }
    
        /** */
        /**
         * <p>
         * 二进制数据编码为BASE64字符串
         * </p>
         * 
         * @param bytes
         * @return
         * @throws Exception
         */
        public static String encode(byte[] bytes) throws Exception
        {
            return new String(Base64.encode(bytes));
        }
    
        /** */
        /**
         * <p>
         * 将文件编码为BASE64字符串
         * </p>
         * <p>
         * 大文件慎用,可能会导致内存溢出
         * </p>
         * 
         * @param filePath
         *            文件绝对路径
         * @return
         * @throws Exception
         */
        public static String encodeFile(String filePath) throws Exception
        {
            byte[] bytes = fileToByte(filePath);
            return encode(bytes);
        }
    
        /** */
        /**
         * <p>
         * BASE64字符串转回文件
         * </p>
         * 
         * @param filePath
         *            文件绝对路径
         * @param base64
         *            编码字符串
         * @throws Exception
         */
        public static void decodeToFile(String filePath, String base64) throws Exception
        {
            byte[] bytes = decode(base64);
            byteArrayToFile(bytes, filePath);
        }
    
        /** */
        /**
         * <p>
         * 文件转换为二进制数组
         * </p>
         * 
         * @param filePath
         *            文件路径
         * @return
         * @throws Exception
         */
        public static byte[] fileToByte(String filePath) throws Exception
        {
            byte[] data = new byte[0];
            File file = new File(filePath);
            if (file.exists())
            {
                FileInputStream in = new FileInputStream(file);
                ByteArrayOutputStream out = new ByteArrayOutputStream(2048);
                byte[] cache = new byte[CACHE_SIZE];
                int nRead = 0;
                while ((nRead = in.read(cache)) != -1)
                {
                    out.write(cache, 0, nRead);
                    out.flush();
                }
                out.close();
                in.close();
                data = out.toByteArray();
            }
            return data;
        }
    
        /** */
        /**
         * <p>
         * 二进制数据写文件
         * </p>
         * 
         * @param bytes
         *            二进制数据
         * @param filePath
         *            文件生成目录
         */
        public static void byteArrayToFile(byte[] bytes, String filePath) throws Exception
        {
            InputStream in = new ByteArrayInputStream(bytes);
            File destFile = new File(filePath);
            if (!destFile.getParentFile().exists())
            {
                destFile.getParentFile().mkdirs();
            }
            destFile.createNewFile();
            OutputStream out = new FileOutputStream(destFile);
            byte[] cache = new byte[CACHE_SIZE];
            int nRead = 0;
            while ((nRead = in.read(cache)) != -1)
            {
                out.write(cache, 0, nRead);
                out.flush();
            }
            out.close();
            in.close();
        }
    
    }
    
  • byte数组及hex转换帮助类

    import java.io.File;
    import java.io.FileWriter;
    import java.io.IOException;
    import java.io.InputStream;
    
    /**
     * byte[] hex数据帮助类
     * 
     * @author lupf
     * 
     */
    public class ByteUtil
    {
    
        static byte[] mask = new byte[128];
    
        static
        {
            initMask();
        }
        static byte[] asciiMask = new byte[]
        { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
    
        private static void initMask()
        { // init mask
            for (int i = 0; i <= 9; i++)
            {
                mask[i + 48] = (byte) i;
            }
            for (int i = 0; i <= 5; i++)
            {
                mask[i + 97] = (byte) (10 + i);
            }
            for (int i = 0; i <= 5; i++)
            {
                mask[i + 65] = (byte) (10 + i);
            }
        }
    
        public static int[] byte2Bitmap(int b)
        {
            int[] bitmap = new int[8];
            for (int i = 0; i < 8; i++)
            {
                bitmap[i] = ((b >> (8 - i - 1)) & 0x01);
            }
            return bitmap;
        }
    
        public static byte[] intToBCD(int n, int balen)
        {
            byte[] ret = new byte[balen];
            int tmp;
            for (int i = 1; i <= balen; i++)
            {
                tmp = n % 100;
                ret[balen - i] = (byte) (tmp / 10 * 16 + tmp % 10);
    
                n -= tmp;
                if (n == 0)
                {
                    break;
                }
                n /= 100;
            }
            return ret;
        }
    
        public static int bcdToInt(byte[] ba, int idx, int len)
        {
            int jinwei = len * 2;
            int ret = 0;
            int temp = 0;
            int pow;
            int posNum; // 正数
            for (int i = 0, n = len; i < n; i++)
            {
                pow = pow(10, (jinwei - 1));
                posNum = ba[idx + i] >= 0 ? ba[idx + i] : ba[idx + i] + 256;
                temp = (posNum / 16) * pow + posNum % 16 * pow / 10;
                ret += temp;
                jinwei -= 2;
            }
            return ret;
        }
    
        public static int pow(int x, int y)
        {
            int n = x;
            for (int i = 1; i < y; i++)
            {
                n *= x;
            }
            return n;
        }
    
        public static byte[] hexStr2Byte(String hex)
        {
            int len = (hex.length() / 2);
            byte[] result = new byte[len];
            char[] achar = hex.toCharArray();
            for (int i = 0; i < len; i++)
            {
                int pos = i * 2;
                result[i] = (byte) (toByte(achar[pos]) << 4 | toByte(achar[pos + 1]));
            }
            return result;
        }
    
        public static int revAsciiHexToInt(byte[] ah)
        {
            int ret = 0;
            for (int i = 0; i < ah.length / 2; i++)
            {
                int hex = (mask[ah[i * 2]] << 4) + (mask[ah[i * 2 + 1]]);
                ret += (hex << (8 * i));
            }
            return ret;
        }
    
        public static int revHexToInt(byte[] data, int off, int len)
        {
            int ret = 0;
            for (int i = 0; i < len; i++)
            {
                ret += (data[off + i] & 0xff) << (8 * i);
            }
    
            return ret;
        }
    
        public static int revAsciiHexToInt(byte[] ah, int off, int len)
        {
            int ret = 0;
            for (int i = 0, n = len / 2; i < n; i++)
            {
                int hex = (mask[ah[i * 2 + off]] << 4) + (mask[ah[i * 2 + off + 1]]);
                ret += (hex << (8 * i));
            }
            return ret;
        }
    
        public static byte[] intToRevAsciiHex(int value, int hexlen)
        {
            byte[] ret = new byte[hexlen * 2];
    
            for (int i = 0; i < hexlen; i++)
            {
                if (value > 0)
                {
                    ret[i * 2] = asciiMask[((value & 0xf0) >> 4)];
                    ret[i * 2 + 1] = asciiMask[(value & 0xf)];
                    value >>= 8;
                }
                else
                {
                    ret[i * 2] = '0';
                    ret[i * 2 + 1] = '0';
                }
            }
            return ret;
        }
    
        public static String intToRevHexString(int value, int hexlen)
        {
    
            byte[] ret = new byte[hexlen];
            for (int i = 0; i < hexlen; i++)
            {
                ret[i] = (byte) (value & 0xff);
                value >>= 8;
                if (value == 0)
                    break;
            }
            return hexToStr(ret);
        }
    
        public static byte[] intToAsciiHex(int value, int len)
        {
            byte[] ret = new byte[len * 2];
            for (int i = 0; i < len; i++)
            {
                ret[i * 2] = asciiMask[((value & 0xf0) >> 4)];
                ret[i * 2 + 1] = asciiMask[value & 0xf];
                value >>= 8;
            }
            return ret;
        }
    
        public static byte[] intToHex(int value, int len)
        {
            byte[] ret = new byte[len];
            for (int i = 0; i < len; i++)
            {
                ret[i] = (byte) ((value >> 8 * (len - i - 1)) & 0xff);
            }
            return ret;
        }
    
        public static byte[] intToRevHex(int value, int len)
        {
            byte[] ret = new byte[len];
            for (int i = 0; i < len; i++)
            {
                ret[i] = (byte) (value & 0xff);
                value >>= 8;
            }
            return ret;
        }
    
        public static int hexToInt(byte[] buf, int idx, int len)
        {
            int ret = 0;
    
            final int e = idx + len;
            for (int i = idx; i < e; ++i)
            {
                ret <<= 8;
                ret |= buf[i] & 0xFF;
            }
            return ret;
        }
    
        public static int hexToInt(byte[] buf)
        {
            return hexToInt(buf, 0, buf.length);
        }
    
        public static String hexToStr(byte[] buf)
        {
            return hexToStr(buf, 0, buf.length);
        }
    
        public static String hexToStr(byte[] buf, int idx, int len)
        {
            StringBuffer sb = new StringBuffer();
            int n;
            for (int i = 0; i < len; i++)
            {
                n = buf[i + idx] & 0xff;
                if (n < 0x10)
                {
                    sb.append("0");
                }
                sb.append(Integer.toHexString(n));
            }
    
            return sb.toString();
        }
    
        private static byte toByte(char c)
        {
            return mask[c];
        }
    
        public static String strToHex(String str)
        {
            try
            {
                byte[] bytes = str.getBytes("GBK");
                StringBuilder sb = new StringBuilder(bytes.length * 2);
                // 转换hex编码
                for (byte b : bytes)
                {
                    sb.append(Integer.toHexString(b + 0x800).substring(1));
                }
                return sb.toString();
            }
            catch (Exception e)
            {
                e.printStackTrace();
            }
            return null;
        }
    
    }
    
    

使用java代码生成公钥私钥

    /**
     * 随机生成密钥对
     * 
     * @param filePath
     *            本地用于存放密钥的路径,如E:/rsa/;那么生成的密钥就会保存在指定的路径下
     */
    public static void genKeyPair(String filePath)
    {
        // KeyPairGenerator类用于生成公钥和私钥对,基于RSA算法生成对象
        File file = new File(filePath);
        if (!file.exists())
            file.mkdirs();

        KeyPairGenerator keyPairGen = null;
        try
        {
            keyPairGen = KeyPairGenerator.getInstance("RSA");
        }
        catch (NoSuchAlgorithmException e)
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        // 初始化密钥对生成器,密钥大小
        keyPairGen.initialize(1024, new SecureRandom());
        // 生成一个密钥对,保存在keyPair中
        KeyPair keyPair = keyPairGen.generateKeyPair();
        // 得到私钥
        RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
        // 得到公钥
        RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
        try
        {
            // 得到公钥字符串
            String publicKeyString = Base64Utils.encode(publicKey.getEncoded());
            // 得到私钥字符串
            String privateKeyString = Base64Utils.encode(privateKey.getEncoded());
            // 将密钥对写入到文件
            FileWriter pubfw = new FileWriter(filePath + "/publicKey.keystore");
            FileWriter prifw = new FileWriter(filePath + "/privateKey.keystore");
            BufferedWriter pubbw = new BufferedWriter(pubfw);
            BufferedWriter pribw = new BufferedWriter(prifw);
            pubbw.write(publicKeyString);
            pribw.write(privateKeyString);
            pubbw.flush();
            pubbw.close();
            pubfw.close();
            pribw.flush();
            pribw.close();
            prifw.close();
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
    }

执行以上代码,即可在指定的文件目录下得到我们需要的公钥及私钥,如下图:

使用openssl生成公钥私钥

  • 资源下载
    这里的openssl是下载的支付宝开放平台下共享的资源,下载入口,进入之后有如下的界面,这里下载的window的版本:

    或者百度云下载
    解压之后,进入到openssl目录,如下图:

  • 密钥生成

    • 第一步:运行“生成公钥私钥转换PCKS8.bat
    • 第二步:运行“私钥转换PCKS8.bat
    • 第三步:同级目录下会出现下图中三个文件

      红框中的2个文件即对应的公钥和私钥,使用notepad++或者UE查看即可。
    • 第四步:需注意以下情况
      通过此方法生成的密钥是以下形式的

      -----BEGIN PUBLIC KEY-----
      MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDP0TVM3bg80cqhA1XcqLCEi3MQ
      bWZYf5Zmwd2mA1C5DbNR1OtsPqemJsJkdTDx4OSuvvUhxHEXJbNPoWx+1ktV+5Cv
      hiytGjwQ5OKWOw9+Iq4Q10IzucgiKMe2NVDK1j9TnNK5SteSw+TUUgaNKS+hNPUq
      vX5jhQDvadE51JIO5wIDAQAB
      -----END PUBLIC KEY-----

      其中—–BEGIN PUBLIC KEY—–和—–END PUBLIC KEY—–为密钥的头和尾,实际使用过程中该部分需要去掉,实际的密钥如下:

      MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDP0TVM3bg80cqhA1XcqLCEi3MQbWZYf5Zmwd2mA1C5DbNR1OtsPqemJsJkdTDx4OSuvvUhxHEXJbNPoWx+1ktV+5CvhiytGjwQ5OKWOw9+Iq4Q10IzucgiKMe2NVDK1j9TnNK5SteSw+TUUgaNKS+hNPUqvX5jhQDvadE51JIO5wIDAQAB

加解密

这里的加解密使用的是通过java代码生成的密钥进行操作及测试

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;

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 javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;

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

    /**
     * 随机生成密钥对
     * 
     * @param filePath
     *            本地用于存放密钥的路径,如E:/rsa/;那么生成的密钥就会保存在指定的路径下
     */
    public static void genKeyPair(String filePath)
    {
        // KeyPairGenerator类用于生成公钥和私钥对,基于RSA算法生成对象
        File file = new File(filePath);
        if (!file.exists())
            file.mkdirs();

        KeyPairGenerator keyPairGen = null;
        try
        {
            keyPairGen = KeyPairGenerator.getInstance("RSA");
        }
        catch (NoSuchAlgorithmException e)
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        // 初始化密钥对生成器,密钥大小为96-1024位
        keyPairGen.initialize(1024, new SecureRandom());
        // 生成一个密钥对,保存在keyPair中
        KeyPair keyPair = keyPairGen.generateKeyPair();
        // 得到私钥
        RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
        // 得到公钥
        RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
        try
        {
            // 得到公钥字符串
            String publicKeyString = Base64Utils.encode(publicKey.getEncoded());
            // 得到私钥字符串
            String privateKeyString = Base64Utils.encode(privateKey.getEncoded());
            // 将密钥对写入到文件
            FileWriter pubfw = new FileWriter(filePath + "/publicKey.keystore");
            FileWriter prifw = new FileWriter(filePath + "/privateKey.keystore");
            BufferedWriter pubbw = new BufferedWriter(pubfw);
            BufferedWriter pribw = new BufferedWriter(prifw);
            pubbw.write(publicKeyString);
            pribw.write(privateKeyString);
            pubbw.flush();
            pubbw.close();
            pubfw.close();
            pribw.flush();
            pribw.close();
            prifw.close();
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
    }

    /**
     * 从文件中输入流中加载公钥
     * 
     * @param in
     *            公钥输入流
     * @throws Exception
     *             加载公钥时产生的异常
     */
    public static String loadPublicKeyByFile(String path) throws Exception
    {
        try
        {
            BufferedReader br = new BufferedReader(new FileReader(path + "/publicKey.keystore"));
            String readLine = null;
            StringBuilder sb = new StringBuilder();
            while ((readLine = br.readLine()) != null)
            {
                sb.append(readLine);
            }
            br.close();
            return sb.toString();
        }
        catch (IOException e)
        {
            throw new Exception("公钥数据流读取错误");
        }
        catch (NullPointerException e)
        {
            throw new Exception("公钥输入流为空");
        }
    }

    /**
     * 从字符串中加载公钥
     * 
     * @param publicKeyStr
     *            公钥数据字符串
     * @throws Exception
     *             加载公钥时产生的异常
     */
    public static RSAPublicKey loadPublicKeyByStr(String publicKeyStr) throws Exception
    {
        try
        {
            byte[] buffer = Base64Utils.decode(publicKeyStr);
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            X509EncodedKeySpec keySpec = new X509EncodedKeySpec(buffer);
            return (RSAPublicKey) keyFactory.generatePublic(keySpec);
        }
        catch (NoSuchAlgorithmException e)
        {
            throw new Exception("无此算法");
        }
        catch (InvalidKeySpecException e)
        {
            throw new Exception("公钥非法");
        }
        catch (NullPointerException e)
        {
            throw new Exception("公钥数据为空");
        }
    }

    /**
     * 从文件中加载私钥
     * 
     * @param keyFileName
     *            私钥文件名
     * @return 是否成功
     * @throws Exception
     */
    public static String loadPrivateKeyByFile(String path) throws Exception
    {
        try
        {
            BufferedReader br = new BufferedReader(new FileReader(path + "/privateKey.keystore"));
            String readLine = null;
            StringBuilder sb = new StringBuilder();
            while ((readLine = br.readLine()) != null)
            {
                sb.append(readLine);
            }
            br.close();
            return sb.toString();
        }
        catch (IOException e)
        {
            throw new Exception("私钥数据读取错误");
        }
        catch (NullPointerException e)
        {
            throw new Exception("私钥输入流为空");
        }
    }

    public static RSAPrivateKey loadPrivateKeyByStr(String privateKeyStr) throws Exception
    {
        try
        {
            byte[] buffer = Base64Utils.decode(privateKeyStr);
            PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(buffer);
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            return (RSAPrivateKey) keyFactory.generatePrivate(keySpec);
        }
        catch (NoSuchAlgorithmException e)
        {
            throw new Exception("无此算法");
        }
        catch (InvalidKeySpecException e)
        {
            throw new Exception("私钥非法");
        }
        catch (NullPointerException e)
        {
            throw new Exception("私钥数据为空");
        }
    }

    /**
     * 公钥加密过程
     * 
     * @param publicKey
     *            公钥
     * @param plainTextData
     *            明文数据
     * @return
     * @throws Exception
     *             加密过程中的异常信息
     */
    public static byte[] encrypt(RSAPublicKey publicKey, byte[] plainTextData) throws Exception
    {
        if (publicKey == null)
        {
            throw new Exception("加密公钥为空, 请设置");
        }
        Cipher cipher = null;
        try
        {
            // 使用默认RSA
            cipher = Cipher.getInstance("RSA");
            // cipher= Cipher.getInstance("RSA", new BouncyCastleProvider());
            cipher.init(Cipher.ENCRYPT_MODE, publicKey);
            byte[] output = cipher.doFinal(plainTextData);
            return output;
        }
        catch (NoSuchAlgorithmException e)
        {
            throw new Exception("无此加密算法");
        }
        catch (NoSuchPaddingException e)
        {
            e.printStackTrace();
            return null;
        }
        catch (InvalidKeyException e)
        {
            throw new Exception("加密公钥非法,请检查");
        }
        catch (IllegalBlockSizeException e)
        {
            throw new Exception("明文长度非法");
        }
        catch (BadPaddingException e)
        {
            throw new Exception("明文数据已损坏");
        }
    }

    /**
     * 私钥加密过程
     * 
     * @param privateKey
     *            私钥
     * @param plainTextData
     *            明文数据
     * @return
     * @throws Exception
     *             加密过程中的异常信息
     */
    public static byte[] encrypt(RSAPrivateKey privateKey, byte[] plainTextData) throws Exception
    {
        if (privateKey == null)
        {
            throw new Exception("加密私钥为空, 请设置");
        }
        Cipher cipher = null;
        try
        {
            // 使用默认RSA
            cipher = Cipher.getInstance("RSA");
            cipher.init(Cipher.ENCRYPT_MODE, privateKey);
            byte[] output = cipher.doFinal(plainTextData);
            return output;
        }
        catch (NoSuchAlgorithmException e)
        {
            throw new Exception("无此加密算法");
        }
        catch (NoSuchPaddingException e)
        {
            e.printStackTrace();
            return null;
        }
        catch (InvalidKeyException e)
        {
            throw new Exception("加密私钥非法,请检查");
        }
        catch (IllegalBlockSizeException e)
        {
            throw new Exception("明文长度非法");
        }
        catch (BadPaddingException e)
        {
            throw new Exception("明文数据已损坏");
        }
    }

    /**
     * 私钥解密过程
     * 
     * @param privateKey
     *            私钥
     * @param cipherData
     *            密文数据
     * @return 明文
     * @throws Exception
     *             解密过程中的异常信息
     */
    public static byte[] decrypt(RSAPrivateKey privateKey, byte[] cipherData) throws Exception
    {
        if (privateKey == null)
        {
            throw new Exception("解密私钥为空, 请设置");
        }
        Cipher cipher = null;
        try
        {
            // 使用默认RSA
            cipher = Cipher.getInstance("RSA");
            // cipher= Cipher.getInstance("RSA", new BouncyCastleProvider());
            cipher.init(Cipher.DECRYPT_MODE, privateKey);
            byte[] output = cipher.doFinal(cipherData);
            return output;
        }
        catch (NoSuchAlgorithmException e)
        {
            throw new Exception("无此解密算法");
        }
        catch (NoSuchPaddingException e)
        {
            e.printStackTrace();
            return null;
        }
        catch (InvalidKeyException e)
        {
            throw new Exception("解密私钥非法,请检查");
        }
        catch (IllegalBlockSizeException e)
        {
            throw new Exception("密文长度非法");
        }
        catch (BadPaddingException e)
        {
            throw new Exception("密文数据已损坏");
        }
    }

    /**
     * 公钥解密过程
     * 
     * @param publicKey
     *            公钥
     * @param cipherData
     *            密文数据
     * @return 明文
     * @throws Exception
     *             解密过程中的异常信息
     */
    public static byte[] decrypt(RSAPublicKey publicKey, byte[] cipherData) throws Exception
    {
        if (publicKey == null)
        {
            throw new Exception("解密公钥为空, 请设置");
        }
        Cipher cipher = null;
        try
        {
            // 使用默认RSA
            cipher = Cipher.getInstance("RSA");
            // cipher= Cipher.getInstance("RSA", new BouncyCastleProvider());
            cipher.init(Cipher.DECRYPT_MODE, publicKey);
            byte[] output = cipher.doFinal(cipherData);
            return output;
        }
        catch (NoSuchAlgorithmException e)
        {
            throw new Exception("无此解密算法");
        }
        catch (NoSuchPaddingException e)
        {
            e.printStackTrace();
            return null;
        }
        catch (InvalidKeyException e)
        {
            throw new Exception("解密公钥非法,请检查");
        }
        catch (IllegalBlockSizeException e)
        {
            throw new Exception("密文长度非法");
        }
        catch (BadPaddingException e)
        {
            throw new Exception("密文数据已损坏");
        }
    }

    /**
     * 字节数据转十六进制字符串
     * 
     * @param data
     *            输入数据
     * @return 十六进制内容
     */
    public static String byteArrayToString(byte[] data)
    {
        StringBuilder stringBuilder = new StringBuilder();
        for (int i = 0; i < data.length; i++)
        {
            // 取出字节的高四位 作为索引得到相应的十六进制标识符 注意无符号右移
            stringBuilder.append(HEX_CHAR[(data[i] & 0xf0) >>> 4]);
            // 取出字节的低四位 作为索引得到相应的十六进制标识符
            stringBuilder.append(HEX_CHAR[(data[i] & 0x0f)]);
            if (i < data.length - 1)
            {
                stringBuilder.append(' ');
            }
        }
        return stringBuilder.toString();
    }
}

数据签名及验签

import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;

/**
 * RSA签名验签类
 */
public class RSASignature
{

    /**
     * 签名算法
     */
    public static final String SIGN_ALGORITHMS = "SHA1WithRSA";

    /**
     * RSA签名,得到base64字符串
     * 
     * @param content
     *            待签名数据
     * @param privateKey
     *            商户私钥
     * @param encode
     *            字符集编码
     * @return 签名值,base64字符串
     */
    public static String signBase64(String content, String privateKey, String encode)
    {
        try
        {
            PKCS8EncodedKeySpec priPKCS8 = new PKCS8EncodedKeySpec(Base64Utils.decode(privateKey));

            KeyFactory keyf = KeyFactory.getInstance("RSA");
            PrivateKey priKey = keyf.generatePrivate(priPKCS8);

            java.security.Signature signature = java.security.Signature.getInstance(SIGN_ALGORITHMS);

            signature.initSign(priKey);
            signature.update(content.getBytes(encode));

            byte[] signed = signature.sign();

            return Base64Utils.encode(signed);
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }

        return null;
    }

    /**
     * RSA签名,得到base64字符串
     * 
     * @param content
     *            待签名数据
     * @param privateKey
     *            商户私钥
     * @return 签名值,base64字符串
     */
    public static String signBase64(String content, String privateKey)
    {
        try
        {
            PKCS8EncodedKeySpec priPKCS8 = new PKCS8EncodedKeySpec(Base64Utils.decode(privateKey));
            KeyFactory keyf = KeyFactory.getInstance("RSA");
            PrivateKey priKey = keyf.generatePrivate(priPKCS8);
            java.security.Signature signature = java.security.Signature.getInstance(SIGN_ALGORITHMS);
            signature.initSign(priKey);
            signature.update(content.getBytes());
            byte[] signed = signature.sign();
            return Base64Utils.encode(signed);
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * RSA验签名检查,数据源为base64字符串
     * 
     * @param content
     *            待签名数据,base64字符串
     * @param sign
     *            签名值
     * @param publicKey
     *            分配给开发商公钥
     * @param encode
     *            字符集编码
     * @return 布尔值
     */
    public static boolean doCheckBase64(String content, String sign, String publicKey, String encode)
    {
        try
        {
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            byte[] encodedKey = Base64Utils.decode(publicKey);
            PublicKey pubKey = keyFactory.generatePublic(new X509EncodedKeySpec(encodedKey));

            java.security.Signature signature = java.security.Signature.getInstance(SIGN_ALGORITHMS);

            signature.initVerify(pubKey);
            signature.update(content.getBytes(encode));

            boolean bverify = signature.verify(Base64Utils.decode(sign));
            return bverify;

        }
        catch (Exception e)
        {
            e.printStackTrace();
        }

        return false;
    }

    /**
     * RSA验签名检查,数据源为base64字符串
     * 
     * @param content
     *            待签名数据,base64字符串
     * @param sign
     *            签名值
     * @param publicKey
     *            分配给开发商公钥
     * @return 布尔值
     */
    public static boolean doCheckBase64(String content, String sign, String publicKey)
    {
        try
        {
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            byte[] encodedKey = Base64Utils.decode(publicKey);
            PublicKey pubKey = keyFactory.generatePublic(new X509EncodedKeySpec(encodedKey));

            java.security.Signature signature = java.security.Signature.getInstance(SIGN_ALGORITHMS);

            signature.initVerify(pubKey);
            signature.update(content.getBytes());

            boolean bverify = signature.verify(Base64Utils.decode(sign));
            return bverify;

        }
        catch (Exception e)
        {
            e.printStackTrace();
        }

        return false;
    }

    /**
     * RSA签名,得到Hex字符串
     * 
     * @param content
     *            待签名数据
     * @param privateKey
     *            商户私钥
     * @param encode
     *            字符集编码
     * @return 签名值,Hex字符串
     */
    public static String signHex(String content, String privateKey, String encode)
    {
        try
        {
            PKCS8EncodedKeySpec priPKCS8 = new PKCS8EncodedKeySpec(Base64Utils.decode(privateKey));

            KeyFactory keyf = KeyFactory.getInstance("RSA");
            PrivateKey priKey = keyf.generatePrivate(priPKCS8);

            java.security.Signature signature = java.security.Signature.getInstance(SIGN_ALGORITHMS);

            signature.initSign(priKey);
            signature.update(content.getBytes(encode));
            byte[] signed = signature.sign();
            return ByteUtil.hexToStr(signed);
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }

        return null;
    }

    /**
     * RSA签名,得到Hex字符串
     * 
     * @param content
     *            待签名数据
     * @param privateKey
     *            商户私钥
     * @return 签名值,Hex字符串
     */
    public static String signHex(String content, String privateKey)
    {
        try
        {
            PKCS8EncodedKeySpec priPKCS8 = new PKCS8EncodedKeySpec(Base64Utils.decode(privateKey));
            KeyFactory keyf = KeyFactory.getInstance("RSA");
            PrivateKey priKey = keyf.generatePrivate(priPKCS8);
            java.security.Signature signature = java.security.Signature.getInstance(SIGN_ALGORITHMS);
            signature.initSign(priKey);
            signature.update(content.getBytes());
            byte[] signed = signature.sign();
            return ByteUtil.hexToStr(signed);
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * RSA验签名检查,数据源为Hex字符串
     * 
     * @param content
     *            待签名数据,Hex字符串
     * @param sign
     *            签名值
     * @param publicKey
     *            分配给开发商公钥
     * @param encode
     *            字符集编码
     * @return 布尔值
     */
    public static boolean doCheckHex(String content, String sign, String publicKey, String encode)
    {
        try
        {
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            byte[] encodedKey = Base64Utils.decode(publicKey);
            PublicKey pubKey = keyFactory.generatePublic(new X509EncodedKeySpec(encodedKey));

            java.security.Signature signature = java.security.Signature.getInstance(SIGN_ALGORITHMS);

            signature.initVerify(pubKey);
            signature.update(content.getBytes(encode));

            boolean bverify = signature.verify(ByteUtil.hexStr2Byte(sign));
            return bverify;

        }
        catch (Exception e)
        {
            e.printStackTrace();
        }

        return false;
    }

    /**
     * RSA验签名检查,数据源为Hex字符串
     * 
     * @param content
     *            待签名数据,Hex字符串
     * @param sign
     *            签名值
     * @param publicKey
     *            分配给开发商公钥
     * @return 布尔值
     */
    public static boolean doCheckHex(String content, String sign, String publicKey)
    {
        try
        {
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            byte[] encodedKey = Base64Utils.decode(publicKey);
            PublicKey pubKey = keyFactory.generatePublic(new X509EncodedKeySpec(encodedKey));

            java.security.Signature signature = java.security.Signature.getInstance(SIGN_ALGORITHMS);

            signature.initVerify(pubKey);
            signature.update(content.getBytes());

            boolean bverify = signature.verify(ByteUtil.hexStr2Byte(sign));
            return bverify;

        }
        catch (Exception e)
        {
            e.printStackTrace();
        }

        return false;
    }
}

数据加解密及签名验签测试

public class MainTest
{
    public static void main(String[] args)
    {
        try
        {
            String filepath = "E:/rsa/";

            RSAEncrypt.genKeyPair(filepath);

            String privateKey = RSAEncrypt.loadPrivateKeyByFile(filepath);
            String publicKey = RSAEncrypt.loadPublicKeyByFile(filepath);

            System.out.println("私钥:" + privateKey);
            System.out.println("公钥:" + publicKey);

            System.out.println("--------------公钥加密私钥解密过程-------------------");
            String data = "rsa公钥加密私钥解密过程";
            // 公钥加密过程
            byte[] cipherData = RSAEncrypt.encrypt(RSAEncrypt.loadPublicKeyByStr(publicKey), data.getBytes());
            // base64的密文数据
            String cipher = Base64Utils.encode(cipherData);
            // hex的密文数据
            String cipherHex = ByteUtil.hexToStr(cipherData);
            // 私钥解密base64的密文过程
            byte[] resBase64 = RSAEncrypt.decrypt(RSAEncrypt.loadPrivateKeyByStr(privateKey), Base64Utils.decode(cipher));
            String restrBase64 = new String(resBase64);

            // 私钥解密hex的密文过程
            byte[] resHex = RSAEncrypt.decrypt(RSAEncrypt.loadPrivateKeyByStr(privateKey), ByteUtil.hexStr2Byte(cipherHex));
            String restrHex = new String(resHex);

            System.out.println("原文:" + data);
            System.out.println("加密(base64):" + cipher);
            System.out.println("加密(hex):" + cipherHex);
            System.out.println("解密(base64):" + restrBase64);
            System.out.println("解密(hex):" + restrHex);
            System.out.println();

            System.out.println("--------------私钥加密公钥解密过程-------------------");
            data = "rsa私钥加密公钥解密过程";
            // 私钥加密过程
            cipherData = RSAEncrypt.encrypt(RSAEncrypt.loadPrivateKeyByStr(privateKey), data.getBytes());
            cipher = Base64Utils.encode(cipherData);
            // 公钥解密过程
            resBase64 = RSAEncrypt.decrypt(RSAEncrypt.loadPublicKeyByStr(publicKey), Base64Utils.decode(cipher));
            restrBase64 = new String(resBase64);
            System.out.println("原文:" + data);
            System.out.println("加密:" + cipher);
            System.out.println("解密:" + restrBase64);
            System.out.println();

            System.out.println("--------------签名及验签测试-----------------------");
            data = "rsa签名及验签测试";

            System.out.println("签名源数据:" + data);
            String singData = RSASignature.signBase64(data, privateKey);
            System.out.println("使用私钥对data数据签名,得到base64的签名数据为:" + singData);
            boolean ckeckVa = RSASignature.doCheckBase64(data, singData, publicKey);
            System.out.println("使用公钥对签名后的base64数据进行验证的结果为:" + ckeckVa);

            System.out.println("");

            singData = RSASignature.signHex(data, privateKey);
            System.out.println("使用私钥对data数据签名,得到hex的签名数据为:" + singData);
            ckeckVa = RSASignature.doCheckHex(data, singData, publicKey);
            System.out.println("使用公钥对签名后的hex数据进行验证的结果为:" + ckeckVa);
        }
        catch (Exception e)
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

运行结果如下图:


到这里rsa密钥的生成,加密解密就完了


注意项

rsa目前只能加密117字节;解密118字节的数据,如果数据太长,不太适合使用rsa加密方式;可以考虑使用对称加密;然后将对称加密的密钥使用rsa加密;然后将加密后的密钥对数据进行加密。

猜你喜欢

转载自blog.csdn.net/lupengfei1009/article/details/78199329