1 package com.byttersoft.hibernate.erp.szmy.util; 2 3 import java.io.ByteArrayInputStream; 4 import java.io.IOException; 5 import java.io.InputStream; 6 import java.io.InputStreamReader; 7 import java.io.Reader; 8 import java.io.StringWriter; 9 import java.io.Writer; 10 import java.security.KeyFactory; 11 import java.security.PrivateKey; 12 import java.security.PublicKey; 13 import java.security.spec.PKCS8EncodedKeySpec; 14 import java.security.spec.X509EncodedKeySpec; 15 import java.util.ArrayList; 16 import java.util.Collections; 17 import java.util.List; 18 import java.util.Map; 19 20 import org.apache.commons.codec.binary.Base64; 21 22 import com.byttersoft.framework.util.StringUtil; 23 /** 24 * RSA的签名及验签 25 * @author zhouyy 26 * 27 */ 28 public class RSA { 29 30 private static final String SIGN_TYPE_RSA = "RSA"; 31 32 private static final String SIGN_TYPE_RSA2 = "RSA2"; 33 34 private static final String SIGN_ALGORITHMS = "SHA1WithRSA"; 35 36 private static final String SIGN_SHA256RSA_ALGORITHMS = "SHA256WithRSA"; 37 38 private static final int DEFAULT_BUFFER_SIZE = 8192; 39 40 /** 41 * RSA/RSA2 生成签名 42 * 43 * @param map 44 * 包含 sign_type、privateKey、charset 45 * @return 46 * @throws Exception 47 */ 48 public static String rsaSign(Map map) throws Exception { 49 PrivateKey priKey = null; 50 java.security.Signature signature = null; 51 String signType = map.get("sign_type").toString(); 52 String privateKey = map.get("privateKey").toString(); 53 String charset = map.get("charset").toString(); 54 String content = getSignContent(map); 55 map.put("content", content); 56 System.out.println("请求参数生成的字符串为:" + content); 57 if (SIGN_TYPE_RSA.equals(signType)) { 58 priKey = getPrivateKeyFromPKCS8(SIGN_TYPE_RSA, new ByteArrayInputStream(privateKey.getBytes())); 59 signature = java.security.Signature.getInstance(SIGN_ALGORITHMS); 60 } else if (SIGN_TYPE_RSA2.equals(signType)) { 61 priKey = getPrivateKeyFromPKCS8(SIGN_TYPE_RSA, new ByteArrayInputStream(privateKey.getBytes())); 62 signature = java.security.Signature.getInstance(SIGN_SHA256RSA_ALGORITHMS); 63 } else { 64 throw new Exception("不是支持的签名类型 : : signType=" + signType); 65 } 66 signature.initSign(priKey); 67 68 if (StringUtil.isEmpty(charset)) { 69 signature.update(content.getBytes()); 70 } else { 71 signature.update(content.getBytes(charset)); 72 } 73 74 byte[] signed = signature.sign(); 75 76 return new String(Base64.encodeBase64(signed)); 77 78 } 79 80 /** 81 * 验签方法 82 * 83 * @param content 84 * 参数的合成字符串格式: key1=value1&key2=value2&key3=value3... 85 * @param sign 86 * @param publicKey 87 * @param charset 88 * @param signType 89 * @return 90 */ 91 public static boolean rsaCheck(Map map, String sign) throws Exception { 92 java.security.Signature signature = null; 93 String signType = map.get("sign_type").toString(); 94 String privateKey = map.get("privateKey").toString(); 95 String charset = map.get("charset").toString(); 96 String content = map.get("content").toString(); 97 String publicKey = map.get("publicKey").toString(); 98 System.out.println(">>验证的签名为:" + sign); 99 System.out.println(">>生成签名的参数为:" + content); 100 PublicKey pubKey = getPublicKeyFromX509("RSA", new ByteArrayInputStream(publicKey.getBytes())); 101 if (SIGN_TYPE_RSA.equals(signType)) { 102 signature = java.security.Signature.getInstance(SIGN_ALGORITHMS); 103 } else if (SIGN_TYPE_RSA2.equals(signType)) { 104 signature = java.security.Signature.getInstance(SIGN_SHA256RSA_ALGORITHMS); 105 } else { 106 throw new Exception("不是支持的签名类型 : signType=" + signType); 107 } 108 signature.initVerify(pubKey); 109 110 if (StringUtil.isEmpty(charset)) { 111 signature.update(content.getBytes()); 112 } else { 113 signature.update(content.getBytes(charset)); 114 } 115 116 return signature.verify(Base64.decodeBase64(sign.getBytes())); 117 } 118 119 public static PrivateKey getPrivateKeyFromPKCS8(String algorithm, InputStream ins) throws Exception { 120 if (ins == null || StringUtil.isEmpty(algorithm)) { 121 return null; 122 } 123 124 KeyFactory keyFactory = KeyFactory.getInstance(algorithm); 125 126 byte[] encodedKey = readText(ins).getBytes(); 127 128 encodedKey = Base64.decodeBase64(encodedKey); 129 130 return keyFactory.generatePrivate(new PKCS8EncodedKeySpec(encodedKey)); 131 } 132 133 public static PublicKey getPublicKeyFromX509(String algorithm, InputStream ins) throws Exception { 134 KeyFactory keyFactory = KeyFactory.getInstance(algorithm); 135 136 StringWriter writer = new StringWriter(); 137 io(new InputStreamReader(ins), writer, -1); 138 139 byte[] encodedKey = writer.toString().getBytes(); 140 141 encodedKey = Base64.decodeBase64(encodedKey); 142 143 return keyFactory.generatePublic(new X509EncodedKeySpec(encodedKey)); 144 } 145 146 /** 147 * 把参数合成成字符串 148 * 149 * @param sortedParams 150 * @return 151 */ 152 public static String getSignContent(Map<String, String> sortedParams) { 153 StringBuffer content = new StringBuffer(); 154 // app_id,method,charset,sign_type,version,bill_type,timestamp,bill_date 155 String[] sign_param = sortedParams.get("sign_param").split(",");// 生成签名所需的参数 156 List<String> keys = new ArrayList<String>(); 157 for (int i = 0; i < sign_param.length; i++) { 158 keys.add(sign_param[i]); 159 } 160 Collections.sort(keys); 161 int index = 0; 162 for (int i = 0; i < keys.size(); i++) { 163 String key = keys.get(i); 164 /*if ("biz_content".equals(key)) { 165 content.append( 166 (index == 0 ? "" : "&") + key + "={"bill_date":"" + sortedParams.get("bill_date") + "",") 167 .append(""bill_type":"" + sortedParams.get("bill_type") + ""}"); 168 index++; 169 } else {*/ 170 String value = sortedParams.get(key); 171 if (StringUtil.isNotEmpty(key) && StringUtil.isNotEmpty(value)) { 172 content.append((index == 0 ? "" : "&") + key + "=" + value); 173 index++; 174 } 175 // } 176 } 177 return content.toString(); 178 } 179 180 private static String readText(InputStream ins) throws IOException { 181 Reader reader = new InputStreamReader(ins); 182 StringWriter writer = new StringWriter(); 183 184 io(reader, writer, -1); 185 return writer.toString(); 186 } 187 188 private static void io(Reader in, Writer out, int bufferSize) throws IOException { 189 if (bufferSize == -1) { 190 bufferSize = DEFAULT_BUFFER_SIZE >> 1; 191 } 192 193 char[] buffer = new char[bufferSize]; 194 int amount; 195 196 while ((amount = in.read(buffer)) >= 0) { 197 out.write(buffer, 0, amount); 198 } 199 } 200 201 }