一、前言
关于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@}