package com.github.ebnew.ki4so.client.key; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.security.Key; import java.util.ArrayList; import java.util.List; import java.util.Properties; import java.util.logging.Level; import java.util.logging.Logger; import javax.crypto.Cipher; import com.github.ebnew.ki4so.core.key.KnightKey; import com.github.ebnew.ki4so.core.key.KnightKeyService; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.NameValuePair; import org.apache.http.client.entity.UrlEncodedFormEntity; import org.apache.http.client.methods.HttpPost; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.message.BasicNameValuePair; import org.apache.http.util.EntityUtils; import sun.misc.BASE64Decoder; import com.alibaba.fastjson.JSON; import com.github.ebnew.ki4so.core.exception.ParamsNotInitiatedCorrectly; /** * 默认的秘钥信息获取实现类,该类只是一个简单的实现,非常不安全。 在生产环境,建议请使用公钥和私钥的方式对秘钥信息 * 进行加密,避免秘钥在公网环境下泄露。请自行加强安全性。 * * @author Administrator */ public class DefaultKeyServiceImpl implements KnightKeyService { private static Logger logger = Logger.getLogger(DefaultKeyServiceImpl.class .getName()); private String ki4soServerFetchKeyUrl; /** 指定私钥存放文件 ,默认是classPath*/ private static String PRIVATE_KEY_PATH = null; /**私钥文件名*/ private static String PRIVATE_KEY_FILE = "PrivateKey"; /** 指定加密算法为RSA */ private static final String ALGORITHM = "RSA"; /** * 本应用的秘钥信息。 */ private KnightKey ki4soKey; /** * 本应用的应用id. */ private String appId; private static DefaultHttpClient httpClient = new DefaultHttpClient(); //默认无参构造方法 public DefaultKeyServiceImpl(){ } public DefaultKeyServiceImpl(String ki4soServerFetchKeyUrl, String appId) { super(); this.ki4soServerFetchKeyUrl = ki4soServerFetchKeyUrl; this.appId = appId; } /* (non-Javadoc) * @see com.github.ebnew.ki4so.core.key.KeyService#findKeyByAppId(java.lang.String) */ @Override public KnightKey findKeyByAppId(String appId) { if (ki4soKey == null) { // do fetch key from remote server. this.ki4soKey = fetchKeyFromKi4soServer(); } return ki4soKey; } private KnightKey fetchKeyFromKi4soServer() { HttpPost httpPost = null; KnightKey ki4so = null; try { httpPost = new HttpPost(ki4soServerFetchKeyUrl); List<NameValuePair> nvps = new ArrayList<NameValuePair>(); nvps.add(new BasicNameValuePair("appId", this.appId)); httpPost.setEntity(new UrlEncodedFormEntity(nvps)); HttpResponse response = httpClient.execute(httpPost); if (response.getStatusLine().getStatusCode() == 200) { HttpEntity entity = response.getEntity(); String content = EntityUtils.toString(entity); EntityUtils.consume(entity); ki4so = JSON.parseObject(content, KnightKey.class); return ki4so; } } catch (Exception e) { logger.log(Level.SEVERE, "fetch ki4so key from server error, the url is ["+ki4soServerFetchKeyUrl+"]", e); } finally { if (httpPost != null) { httpPost.releaseConnection(); } } return null; } /* (non-Javadoc) * @see com.github.ebnew.ki4so.core.key.KeyService#findKeyByKeyId(java.lang.String) */ @Override public KnightKey findKeyByKeyId(String keyId) { if (ki4soKey == null) { return this.findKeyByAppId(null); } return ki4soKey; } /** * @param keyValue 需解密的key字符串 * @param token 标识privateKey * @return 解密后的key */ public String decryptKey(String token,String keyValue){ String decryptKey = null; //解密后的密文 //检测私钥文件是否存在 if(!checkKeyFileExistByToken(token)){ throw new ParamsNotInitiatedCorrectly("The Private Key File Is Not Initiated !!!"); } Key privateKey = loadPrivateKey(); //加载文件私钥 /** 得到Cipher对象对已用公钥加密的数据进行RSA解密 */ Cipher cipher; try { cipher = Cipher.getInstance(ALGORITHM); cipher.init(Cipher.DECRYPT_MODE, privateKey); BASE64Decoder decoder = new BASE64Decoder(); byte[] bytes = decoder.decodeBuffer(keyValue); /** 执行解密操作 */ byte[] decryptValue = cipher.doFinal(bytes); decryptKey = new String(decryptValue); //decryptValue[]转换成String } catch (Exception e) { // TODO Auto-generated catch block logger.log(Level.WARNING, "Cipher error used by private key !!", e); } return decryptKey; } /** * @return 用Base64加密后的私钥文件 * @throws Exception */ public Key loadPrivateKey(){ Key privateKey = null; ObjectInputStream ois = null; try { /** 将文件中的私钥对象读出 */ ois = new ObjectInputStream(new FileInputStream( PRIVATE_KEY_FILE)); privateKey = (Key) ois.readObject(); } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (ClassNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); }finally{ if(ois != null){ try { ois.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } return privateKey; } /* (non-Javadoc) * @see com.github.ebnew.ki4so.core.key.KeyService#checkKeyFileExistByToken(java.lang.String) */ @Override public boolean checkKeyFileExistByToken(String token) { // TODO Auto-generated method stub Properties property = new Properties(); //初始化文件输入流 InputStream in = null; try { in = DefaultKeyServiceImpl.class.getResourceAsStream("/keySecurity.properties"); property.load(in); } catch (FileNotFoundException e) { // TODO Auto-generated catch block logger.log(Level.WARNING, "keySecurity File Is Not Found,The Filepath Info Read Fail!", e); } catch (IOException e) { // TODO Auto-generated catch block logger.log(Level.WARNING, "keySecurity File Load Fail!", e); } //从配置文件中获取私钥存放位置 PRIVATE_KEY_PATH = property.getProperty("keyPath"); //配置文件中指定私钥的存放位置 if(PRIVATE_KEY_PATH != null || !"".equals(PRIVATE_KEY_PATH)){ PRIVATE_KEY_FILE = PRIVATE_KEY_PATH + PRIVATE_KEY_FILE; } File file = new File(PRIVATE_KEY_FILE); return file.exists(); } /* (non-Javadoc) * @see com.github.ebnew.ki4so.core.key.KeyService#generateKeyFile() */ @Override public Object generateKeyFile(String token) throws Exception{ // TODO Auto-generated method stubj String keyFile = null; //获取服务器端生成秘钥 HttpPost httpPost = null; //判断运用ID列表是否为空 if(token == null || "".equals(token)){ throw new ParamsNotInitiatedCorrectly("Token Parameter Is Initiated Incorrently !!"); } //私钥文件已存在 if(checkKeyFileExistByToken(token)){ return false; } try { httpPost = new HttpPost(ki4soServerFetchKeyUrl); List<NameValuePair> nvps = new ArrayList<NameValuePair>(); nvps.add(new BasicNameValuePair("appId", this.appId)); httpPost.setEntity(new UrlEncodedFormEntity(nvps)); HttpResponse response = httpClient.execute(httpPost); if (response.getStatusLine().getStatusCode() == 200) { HttpEntity entity = response.getEntity(); keyFile = EntityUtils.toString(entity); } } catch (Exception e) { logger.log(Level.SEVERE, "fetch ki4so key from server error, the url is ["+ki4soServerFetchKeyUrl+"]", e); } finally { if (httpPost != null) { httpPost.releaseConnection(); } } //用Base64解密私钥 @SuppressWarnings("restriction") BASE64Decoder decoder = new BASE64Decoder(); @SuppressWarnings("restriction") byte[] bytes = decoder.decodeBuffer(keyFile); keyFile = new String(bytes); //将私钥写入客户端 ObjectOutputStream keyOutPutStream = null; try { /** 用对象流将生成的密钥写入文件 */ keyOutPutStream = new ObjectOutputStream(new FileOutputStream(PRIVATE_KEY_FILE)); keyOutPutStream.writeObject(keyFile); } catch (Exception e) { throw e; } finally{ /** 清空缓存,关闭文件输出流 */ keyOutPutStream.close(); } return true; } }