话不多说,代码如下
1 package com.syl.test_key; 2 3 import lombok.extern.slf4j.Slf4j; 4 import org.apache.commons.codec.binary.Base64; 5 import sun.misc.BASE64Decoder; 6 import sun.misc.BASE64Encoder; 7 8 import java.io.UnsupportedEncodingException; 9 import java.security.*; 10 import java.security.interfaces.RSAPrivateKey; 11 import java.security.interfaces.RSAPublicKey; 12 import java.security.spec.PKCS8EncodedKeySpec; 13 import java.security.spec.X509EncodedKeySpec; 14 import java.util.HashMap; 15 import java.util.Iterator; 16 import java.util.Map; 17 import java.util.TreeMap; 18 19 /** 20 * Created by 孙义朗 on 2017/11/24 0024. 21 */ 22 @Slf4j 23 public class KeyUtil { 24 public static final String KEY_ALGORTHM = "RSA";// 25 public static final String SIGNATURE_ALGORITHM = "SHA1WithRSA"; 26 public static final String PUBLIC_KEY = "RSAPublicKey";//公钥 27 public static final String PRIVATE_KEY = "RSAPrivateKey";//私钥 28 29 //map对象中存放公私钥(初始化,生成一对公钥和私钥) 1 30 public static Map<String, Object> initKey() throws Exception { 31 //获得对象 KeyPairGenerator 参数 RSA 1024个字节 32 KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(KEY_ALGORTHM); 33 keyPairGen.initialize(1024); 34 //通过对象 KeyPairGenerator 获取对象KeyPair 35 KeyPair keyPair = keyPairGen.generateKeyPair(); 36 37 //通过对象 KeyPair 获取RSA公私钥对象RSAPublicKey RSAPrivateKey 38 RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic(); 39 RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate(); 40 //公私钥对象存入map中 41 Map<String, Object> keyMap = new HashMap<String, Object>(2); 42 keyMap.put(PUBLIC_KEY, publicKey); 43 keyMap.put(PRIVATE_KEY, privateKey); 44 return keyMap; 45 } 46 47 /** 48 * 获得公钥 2 49 */ 50 public static String getPublicKey(Map<String, Object> keyMap) throws Exception { 51 //获得map中的公钥对象 转为key对象 52 Key key = (Key) keyMap.get(PUBLIC_KEY); 53 //编码返回字符串 2.1 54 return encryptBASE64(key.getEncoded()); 55 } 56 57 //编码返回字符串 2.1(3.1) 58 public static String encryptBASE64(byte[] key) throws Exception { 59 return (new BASE64Encoder()).encodeBuffer(key); 60 } 61 62 /** 63 * 获得私钥 3 64 */ 65 public static String getPrivateKey(Map<String, Object> keyMap) throws Exception { 66 //获得map中的私钥对象 转为key对象 67 Key key = (Key) keyMap.get(PRIVATE_KEY); 68 //编码返回字符串 3.1 69 return encryptBASE64(key.getEncoded()); 70 } 71 72 73 /** 74 * 根据私钥,生成数字签名 4 75 */ 76 public static String getSign(TreeMap<String, Object> map, String privateKey) { 77 try { 78 log.info("****** privateKey : " + privateKey); 79 80 //获取待签名的字符串 4.1 81 String result = getValue(map); 82 log.info("****** 参与签名的字符串为:[" + result + "]"); 83 //信息加密,生成数字签名 4.2 84 return KeyUtil.sign(result.getBytes("utf-8"), privateKey); 85 } catch (Exception e) { 86 log.info("****** 签名异常", e); 87 return ""; 88 } 89 } 90 91 //获取待签名的字符串 4.1(5.1) 92 public static String getValue(TreeMap<String, Object> map) throws Exception { 93 log.info("****** 加签字符串:[" + map.toString() + "]"); 94 map.remove("sign");// 移除上送上来的sign字段 95 StringBuilder sb = new StringBuilder(); 96 Iterator<Map.Entry<String, Object>> iter = map.entrySet().iterator(); 97 while (iter.hasNext()) { 98 Map.Entry<String, Object> entry = iter.next(); 99 sb.append(entry.getValue() == null ? "" : entry.getValue()); 100 } 101 String result = sb.toString(); 102 103 return result; 104 } 105 106 //用私钥对需要加密的信息加密 4.2 107 public static String sign(byte[] data, String privateKey) throws Exception { 108 //解密私钥 109 byte[] keyBytes = Base64.decodeBase64(privateKey); 110 //构造PKCS8EncodedKeySpec对象 111 PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(keyBytes); 112 //指定加密算法 113 KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORTHM); 114 //取私钥匙对象 115 PrivateKey privateKey2 = keyFactory.generatePrivate(pkcs8EncodedKeySpec); 116 //用私钥对信息生成数字签名 117 Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM); 118 signature.initSign(privateKey2); 119 signature.update(data); 120 121 return Base64.encodeBase64String(signature.sign()); 122 } 123 124 /** 125 * 用公钥,校验签名 5 126 */ 127 public static boolean vertifySign(TreeMap<String, Object> map, String sign, String publicKey) { 128 try { 129 log.info("****** publicKey : " + publicKey); 130 131 //获取待校验的字符串 5.1 132 String result = getValue(map); 133 log.info("****** 参与验签的字符串为:[" + result + "]"); 134 //校验数字签名 5.2 135 return KeyUtil.verify(result.getBytes("utf-8"), publicKey, sign); 136 } catch (UnsupportedEncodingException e) { 137 log.error("****** 校验签名异常", e); 138 return false; 139 } catch (Exception e) { 140 log.error("****** 校验签名异常", e); 141 return false; 142 } 143 } 144 145 //校验数字签名(校验签名使用) 5.2 146 public static boolean verify(byte[] data, String publicKey, String sign) throws Exception { 147 //解密公钥 148 byte[] keyBytes = Base64.decodeBase64(publicKey); 149 //构造X509EncodedKeySpec对象 150 X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(keyBytes); 151 //指定加密算法 152 KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORTHM); 153 //取公钥匙对象 154 PublicKey publicKey2 = keyFactory.generatePublic(x509EncodedKeySpec); 155 156 Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM); 157 signature.initVerify(publicKey2); 158 signature.update(data); 159 //验证签名是否正常 160 return signature.verify(Base64.decodeBase64(sign)); 161 } 162 163 164 //解码返回byte 165 public static byte[] decryptBASE64(String key) throws Exception { 166 return (new BASE64Decoder()).decodeBuffer(key); 167 } 168 169 }
测试类
1 package com.syl.test_key; 2 3 import java.util.Map; 4 import java.util.TreeMap; 5 6 /** 7 * Created by 孙义朗 on 2017/11/24 0024. 8 */ 9 public class TestKey { 10 public static void main(String[] args) throws Exception { 11 //新建一个需要加签的信息 12 TreeMap<String, Object> treeMap = new TreeMap(); 13 treeMap.put("name", "syl"); 14 treeMap.put("age", 18); 15 16 //map对象中存放公私钥 17 Map<String, Object> keyMap = KeyUtil.initKey(); 18 19 //获得公钥和私钥 20 String publicKey = KeyUtil.getPublicKey(keyMap); 21 String privateKey = KeyUtil.getPrivateKey(keyMap); 22 23 //获取签名 24 String sign = KeyUtil.getSign(treeMap, privateKey); 25 26 //验证签名 27 boolean flag = KeyUtil.vertifySign(treeMap, sign, publicKey); 28 if (flag) { 29 System.out.println("验证成功!"); 30 } else { 31 System.err.println("验证失败"); 32 } 33 } 34 }
控制台输出