package com.github.ebnew.ki4so.core.key; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.TypeReference; import com.github.ebnew.ki4so.common.utils.StringUtils; import com.github.ebnew.ki4so.core.dao.fs.KnightFileSystemDao; import org.apache.log4j.Logger; import sun.misc.BASE64Encoder; import javax.crypto.Cipher; import javax.crypto.NoSuchPaddingException; import java.io.*; import java.security.*; import java.util.HashMap; import java.util.List; import java.util.Map; /** * 默认的key管理实现类,从classpath:/keys.js文件中 * 读取key配置信息,是以json格式存储的 * @author zhenglu * @since 15/4/24 */ public class KnightKeyServiceImpl extends KnightFileSystemDao implements KnightKeyService{ private static final Logger logger = Logger.getLogger(KnightKeyServiceImpl.class); public static final String DEFALUT_EXTERNAL_DATA = ""; public static final String DEFALUT_CLASSPATH_DATA = "keys.js"; private static String PUBLIC_KEY_PATH = null; private static String PUBLIC_KEY_FILE = null; private static final String ALGORITHM = "RSA"; private static final int KEY_SIZE = 1024; /** * 密钥映射表 key是keyId,value是key对象 */ private Map<String,KnightKey> keyMap = new HashMap<String, KnightKey>(); /** * 密钥映射表,key是appid,value是Key对象 */ private Map<String,KnightKey> appIdMap = new HashMap<String, KnightKey>(); protected void init(){ this.externalData = DEFALUT_EXTERNAL_DATA; this.classPathData = DEFALUT_CLASSPATH_DATA; loadAppData(); } @Override protected void loadAppData() { try{ String content = this.readDataFromFile(); // 将读取的应用列表转换为应用map List<KnightKey> keyList = JSON.parseObject(content,new TypeReference<List<KnightKey>>(){}); for(KnightKey key:keyList){ keyMap.put(key.getKeyId(),key); appIdMap.put(key.getAppId(),key); } }catch (Exception e){ logger.error("loadAppData has error " + e.getMessage()); } } @Override public KnightKey findKeyByKeyId(String keyId) { KnightKey key = null; if(!StringUtils.isEmpty(keyId)){ return this.keyMap.get(keyId); } return null; } @Override public KnightKey findKeyByAppId(String appId) { KnightKey key = null; if(!StringUtils.isEmpty(appId)){ return this.appIdMap.get(appId); } return null; } /** * 用Base64加密后的私钥文件 * @return */ public Key loadPublicKey(){ Key keyPublic = null; ObjectInputStream inputStream = null; try { inputStream = new ObjectInputStream(new FileInputStream(PUBLIC_KEY_FILE)); keyPublic = (Key)inputStream.readObject(); } catch (IOException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); }finally { if(inputStream != null){ try { inputStream.close(); } catch (IOException e) { e.printStackTrace(); } } } return keyPublic; } /** * 对公钥进行base64加密 * @param appId * @param keyValue * @return */ public String encryptKey(String appId,String keyValue){ if(checkKeyFileExistByToken(appId)){ //判断公钥文件是否存在 Key publicKey = loadPublicKey(); //加载公钥文件 try { Cipher cipher = Cipher.getInstance(ALGORITHM); cipher.init(Cipher.ENCRYPT_MODE,publicKey); byte[] bytes = keyValue.getBytes(); byte[] encryptValue = cipher.doFinal(bytes); BASE64Encoder encoder = new BASE64Encoder(); String encryptKey = encoder.encode(encryptValue); return encryptKey; } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } catch (NoSuchPaddingException e) { e.printStackTrace(); }catch (Exception e){ e.printStackTrace(); } } return null; } @Override public boolean checkKeyFileExistByToken(String appId) { if(!StringUtils.isEmpty(appId)){ KnightKey key = appIdMap.get(appId); PUBLIC_KEY_PATH = key.getKeyPath(); //获取公钥文件的存放路径 PUBLIC_KEY_FILE = PUBLIC_KEY_PATH + appId; File file = new File(PUBLIC_KEY_FILE); return file.exists(); } return false; } /** * 生成密钥,将公钥写入文件,返回私钥 * @param token * @return */ @Override public Object generateKeyFile(String token) { if(appIdMap == null || StringUtils.isEmpty(token)){ logger.info("appIdMap Parameter Is Initiated Incorrently !!"); return null; } // RSA算法要求有一个可信任的随机源 SecureRandom random = new SecureRandom(); ObjectOutputStream outputStream = null; Key privateKey = null; try { //为RSA算法创建一个keyPairGenerator对象 KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(ALGORITHM); //利用上面的随机数据源初始化这个keyPairGenerator keyPairGenerator.initialize(KEY_SIZE,random); //生成密钥对 KeyPair keyPair = keyPairGenerator.generateKeyPair(); // 得到公钥 Key publicKey = keyPair.getPublic(); //得到私钥 privateKey = keyPair.getPrivate(); outputStream = new ObjectOutputStream(new FileOutputStream(PUBLIC_KEY_FILE)); /** 用对象流将公钥写入文件 **/ outputStream.writeObject(publicKey); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); }catch (Exception e){ e.printStackTrace(); }finally { /** 清空buffer缓存,关闭文件输出流**/ if(outputStream != null){ try { outputStream.close(); } catch (IOException e) { e.printStackTrace(); } } } return privateKey; } }