首页

关于RSA公钥/私钥/签名工具包RSAUtils实现密钥对生成、数字签名生成校验等处理

标签:RSA公钥私钥,签名工具包,RSAUtils,密钥对生成,数字签名     发布时间:2018-06-25   

一、前言

关于RSA公钥/私钥/签名RSAUtils工具包类,提供生成密钥对(公钥和私钥)-genKeyPair、用私钥对信息生成数字签名(sign)、校验数字签名(verify)、私钥解密(decryptByPrivateKey)、公钥解密(decryptByPublicKey)、公钥加密(encryptByPublicKey)、私钥加密(encryptByPrivateKey)、获取私钥(getPrivateKey)、获取公钥(getPublicKey)、获取校验码(getVerifyCode)等方法,详情参见代码示例部分。

二、代码示例

import java.io.ByteArrayOutputStream;@b@import java.security.Key;@b@import java.security.KeyFactory;@b@import java.security.KeyPair;@b@import java.security.KeyPairGenerator;@b@import java.security.PrivateKey;@b@import java.security.PublicKey;@b@import java.security.Signature;@b@import java.security.interfaces.RSAPrivateKey;@b@import java.security.interfaces.RSAPublicKey;@b@import java.security.spec.PKCS8EncodedKeySpec;@b@import java.security.spec.X509EncodedKeySpec;@b@import java.util.HashMap;@b@import java.util.Map;@b@@b@import javax.crypto.Cipher;@b@@b@/** @b@* <p>@b@* RSA公钥/私钥/签名工具包@b@* </p> @b@* <p>@b@* 字符串格式的密钥在未在特殊说明情况下都为BASE64编码格式<br/>@b@* 由于非对称加密速度极其缓慢,一般文件不使用它来加密而是使用对称加密,<br/>@b@* 非对称加密算法可以用来对对称加密的密钥加密,这样保证密钥的安全也就保证了数据的安全@b@* </p> @b@*/@b@public class RSAUtils {@b@@b@   /** @b@   * 算法供应商@b@   */@b@   public static final String ALG_PROVIDER = "mockAlgorithm";@b@   @b@    /** @b@     * 加密算法RSA@b@     */@b@    public static final String KEY_ALGORITHM = "RSA";@b@    @b@    /** @b@     * 01-身份证@b@     */@b@    public static final String ID_CARD= "01";@b@    @b@    /** @b@     * 签名算法@b@     */@b@    public static final String SIGNATURE_ALGORITHM = "MD5withRSA";@b@@b@    /** @b@     * 获取公钥的key@b@     */@b@    private static final String PUBLIC_KEY = "RSAPublicKey";@b@    @b@    /** @b@     * 获取私钥的key@b@     */@b@    private static final String PRIVATE_KEY = "RSAPrivateKey";@b@    @b@    private static final int KEY_SIZE = 2048;     @b@    @b@    /** @b@     * RSA最大加密明文大小@b@     */@b@    private static final int MAX_ENCRYPT_BLOCK = KEY_SIZE / 8 - 11;@b@    @b@    /** @b@     * RSA最大解密密文大小@b@     */@b@    private static final int MAX_DECRYPT_BLOCK = KEY_SIZE / 8;@b@    @b@   @b@@b@    /** @b@     * <p>@b@     * 生成密钥对(公钥和私钥)@b@     * </p>@b@     * @b@     * @return@b@     * @throws Exception@b@     */@b@    public static Map<String, Object> genKeyPair() throws Exception {@b@        KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(KEY_ALGORITHM);@b@        keyPairGen.initialize(KEY_SIZE);@b@        KeyPair keyPair = keyPairGen.generateKeyPair();@b@        RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();@b@        RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();@b@        Map<String, Object> keyMap = new HashMap<String, Object>(2);@b@        keyMap.put(PUBLIC_KEY, publicKey);@b@        keyMap.put(PRIVATE_KEY, privateKey);@b@        return keyMap;@b@    }@b@    @b@    /** @b@     * <p>@b@     * 用私钥对信息生成数字签名@b@     * </p>@b@     * @b@     * @param data 已加密数据@b@     * @param privateKey 私钥(BASE64编码)@b@     * @b@     * @return@b@     * @throws Exception@b@     */@b@    public static String sign(byte[] data, String privateKey) throws Exception {@b@        byte[] keyBytes = Base64Utils.decode(privateKey);@b@        PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);@b@        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);@b@        PrivateKey privateK = keyFactory.generatePrivate(pkcs8KeySpec);@b@        Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);@b@        signature.initSign(privateK);@b@        signature.update(data);@b@        return Base64Utils.encode(signature.sign());@b@    }@b@@b@    /** @b@     * <p>@b@     * 校验数字签名@b@     * </p>@b@     * @b@     * @param data 已加密数据@b@     * @param publicKey 公钥(BASE64编码)@b@     * @param sign 数字签名@b@     * @b@     * @return@b@     * @throws Exception@b@     * @b@     */@b@    public static boolean verify(byte[] data, String publicKey, String sign)@b@            throws Exception {@b@        byte[] keyBytes = Base64Utils.decode(publicKey);@b@        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);@b@        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);@b@        PublicKey publicK = keyFactory.generatePublic(keySpec);@b@        Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);@b@        signature.initVerify(publicK);@b@        signature.update(data);@b@        return signature.verify(Base64Utils.decode(sign));@b@    }@b@@b@    /** @b@     * <P>@b@     * 私钥解密@b@     * </p>@b@     * @b@     * @param encryptedData 已加密数据@b@     * @param privateKey 私钥(BASE64编码)@b@     * @return@b@     * @throws Exception@b@     */@b@    public static byte[] decryptByPrivateKey(byte[] encryptedData, String privateKey)@b@            throws Exception {@b@        byte[] keyBytes = Base64Utils.decode(privateKey);@b@        PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);@b@        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);@b@        Key privateK = keyFactory.generatePrivate(pkcs8KeySpec);@b@        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());@b@        cipher.init(Cipher.DECRYPT_MODE, privateK);@b@        int inputLen = encryptedData.length;@b@        ByteArrayOutputStream out = new ByteArrayOutputStream();@b@        int offSet = 0;@b@        byte[] cache;@b@        int i = 0;@b@        // 对数据分段解密@b@        while (inputLen - offSet > 0) {@b@            if (inputLen - offSet > MAX_DECRYPT_BLOCK) {@b@                cache = cipher.doFinal(encryptedData, offSet, MAX_DECRYPT_BLOCK);@b@            } else {@b@                cache = cipher.doFinal(encryptedData, offSet, inputLen - offSet);@b@            }@b@            out.write(cache, 0, cache.length);@b@            i++;@b@            offSet = i * MAX_DECRYPT_BLOCK;@b@        }@b@        byte[] decryptedData = out.toByteArray();@b@        out.close();@b@        return decryptedData;@b@    }@b@@b@    /** @b@     * <p>@b@     * 公钥解密@b@     * </p>@b@     * @b@     * @param encryptedData 已加密数据@b@     * @param publicKey 公钥(BASE64编码)@b@     * @return@b@     * @throws Exception@b@     */@b@    public static byte[] decryptByPublicKey(byte[] encryptedData, String publicKey)@b@            throws Exception {@b@        byte[] keyBytes = Base64Utils.decode(publicKey);@b@        X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);@b@        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);@b@        Key publicK = keyFactory.generatePublic(x509KeySpec);@b@        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());@b@        cipher.init(Cipher.DECRYPT_MODE, publicK);@b@        int inputLen = encryptedData.length;@b@        ByteArrayOutputStream out = new ByteArrayOutputStream();@b@        int offSet = 0;@b@        byte[] cache;@b@        int i = 0;@b@        // 对数据分段解密@b@        while (inputLen - offSet > 0) {@b@            if (inputLen - offSet > MAX_DECRYPT_BLOCK) {@b@                cache = cipher.doFinal(encryptedData, offSet, MAX_DECRYPT_BLOCK);@b@            } else {@b@                cache = cipher.doFinal(encryptedData, offSet, inputLen - offSet);@b@            }@b@            out.write(cache, 0, cache.length);@b@            i++;@b@            offSet = i * MAX_DECRYPT_BLOCK;@b@        }@b@        byte[] decryptedData = out.toByteArray();@b@        out.close();@b@        return decryptedData;@b@    }@b@@b@    /** @b@     * <p>@b@     * 公钥加密@b@     * </p>@b@     * @b@     * @param data 源数据@b@     * @param publicKey 公钥(BASE64编码)@b@     * @return@b@     * @throws Exception@b@     */@b@    public static byte[] encryptByPublicKey(byte[] data, String publicKey)@b@            throws Exception {@b@        byte[] keyBytes = Base64Utils.decode(publicKey);@b@        X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);@b@        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);@b@        Key publicK = keyFactory.generatePublic(x509KeySpec);@b@        // 对数据加密@b@        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());@b@        cipher.init(Cipher.ENCRYPT_MODE, publicK);@b@        int inputLen = data.length;@b@        ByteArrayOutputStream out = new ByteArrayOutputStream();@b@        int offSet = 0;@b@        byte[] cache;@b@        int i = 0;@b@        // 对数据分段加密@b@        while (inputLen - offSet > 0) {@b@            if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {@b@                cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK);@b@            } else {@b@                cache = cipher.doFinal(data, offSet, inputLen - offSet);@b@            }@b@            out.write(cache, 0, cache.length);@b@            i++;@b@            offSet = i * MAX_ENCRYPT_BLOCK;@b@        }@b@        byte[] encryptedData = out.toByteArray();@b@        out.close();@b@        return encryptedData;@b@    }@b@@b@    /** @b@     * <p>@b@     * 私钥加密@b@     * </p> @b@     * @param data 源数据@b@     * @param privateKey 私钥(BASE64编码)@b@     * @return@b@     * @throws Exception@b@     */@b@    public static byte[] encryptByPrivateKey(byte[] data, String privateKey)@b@            throws Exception {@b@        byte[] keyBytes = Base64Utils.decode(privateKey);@b@        PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);@b@        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);@b@        Key privateK = keyFactory.generatePrivate(pkcs8KeySpec);@b@        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());@b@        cipher.init(Cipher.ENCRYPT_MODE, privateK);@b@        int inputLen = data.length;@b@        ByteArrayOutputStream out = new ByteArrayOutputStream();@b@        int offSet = 0;@b@        byte[] cache;@b@        int i = 0;@b@        // 对数据分段加密@b@        while (inputLen - offSet > 0) {@b@            if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {@b@                cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK);@b@            } else {@b@                cache = cipher.doFinal(data, offSet, inputLen - offSet);@b@            }@b@            out.write(cache, 0, cache.length);@b@            i++;@b@            offSet = i * MAX_ENCRYPT_BLOCK;@b@        }@b@        byte[] encryptedData = out.toByteArray();@b@       out.close();@b@        return encryptedData;@b@    }@b@@b@    /** @b@     * <p>@b@     * 获取私钥@b@     * </p> @b@     * @param keyMap 密钥对@b@     * @return@b@     * @throws Exception@b@     */@b@    public static String getPrivateKey(Map<String, Object> keyMap)@b@            throws Exception {@b@        Key key = (Key) keyMap.get(PRIVATE_KEY);@b@        return Base64Utils.encode(key.getEncoded());@b@    }@b@@b@    /** @b@     * <p>@b@     * 获取公钥@b@     * </p>@b@     * @b@     * @param keyMap 密钥对@b@     * @return@b@     * @throws Exception@b@     */@b@    public static String getPublicKey(Map<String, Object> keyMap)@b@            throws Exception {@b@        Key key = (Key) keyMap.get(PUBLIC_KEY);@b@        return Base64Utils.encode(key.getEncoded());@b@    }@b@@b@    public static String getEighteenIDCard(String fifteenIDCard){  @b@        StringBuilder sb = new StringBuilder();  @b@        sb.append(fifteenIDCard.substring(0, 6))  @b@        .append("19")  @b@        .append(fifteenIDCard.substring(6));  @b@        sb.append(getVerifyCode(sb.toString()));  @b@        return sb.toString();  @b@    }  @b@    @b@    /** @b@     * 获取校验码 @b@     * @param idCardNumber 不带校验位的身份证号码(17位) @b@     * @return 校验码 @b@     * @throws Exception 如果身份证没有加上19,则抛出异常 @b@     */  @b@    private static char getVerifyCode(String idCardNumber){  @b@      char[] Ai = idCardNumber.toCharArray();  @b@      int[] Wi = {7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2};  @b@      char[] verifyCode = {'1','0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'};  @b@      int S = 0;  @b@      int Y;  @b@      for(int i = 0; i < Wi.length; i++){  @b@        S += (Ai[i] - '0') * Wi[i];  @b@      }  @b@      Y = S % 11;  @b@      return verifyCode[Y];  @b@    }@b@    @b@    public static void main(String[] args) throws Exception {@b@      Map m = genKeyPair();@b@      System.out.println(getPrivateKey(m));@b@      System.out.println(getPublicKey(m));@b@   }@b@}