Java tutorial
/* Copyright 2012-2013, Polyvi Inc. (http://polyvi.github.io/openxface) This program is distributed under the terms of the GNU General Public License. This file is part of xFace. xFace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. xFace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with xFace. If not, see <http://www.gnu.org/licenses/>. */ package com.polyvi.xface.extension; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.io.UnsupportedEncodingException; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import com.polyvi.xface.exception.XCryptionException; import com.polyvi.xface.plugin.api.XIWebContext; import com.polyvi.xface.util.XBase64; import com.polyvi.xface.util.XCryptor; import com.polyvi.xface.util.XFileUtils; import com.polyvi.xface.util.XLog; import com.polyvi.xface.util.XPathResolver; import com.polyvi.xface.util.XStringUtils; public class XSecurityExt extends XExtension { private static final String CLASS_NAME = XSecurityExt.class.getSimpleName(); /** Security ??js??? */ private static final String COMMAND_ENCRYPT = "encrypt"; private static final String COMMAND_DECRYPT = "decrypt"; private static final String COMMAND_ENCRYPT_FILE = "encryptFile"; private static final String COMMAND_DECRYPT_FILE = "decryptFile"; private static final String COMMAND_DIGEST = "digest"; /** */ private static final int FILE_NOT_FOUND_ERR = 1; private static final int PATH_ERR = 2; private static final int OPERATION_ERR = 3; /***/ private static final String KEY_EMPTY_ERROR = "Error:key null or empty"; private static final String FILE_NOT_FOUND_ERROR = "Error: file not found"; private static final String CRYPTION_ERROR = "Error:cryption error"; /***/ private static final int DES_ALOGRITHEM = 1; //DES? private static final int TRIPLE_DES_ALOGRITHEM = 2;//3DES? private static final int RSA_ALOGRITHEM = 3; //RSA? /**?*/ private static final int ENCODE_TYPE_STRING = 0; //?String private static final int ENCODE_TYPE_BASE64 = 1;//?Base64?? private static final int ENCODE_TYPE_HEX = 2;//?16?? /** ??? */ private static final String KEY_CRYPT_ALGORITHM = "CryptAlgorithm"; private static final String KEY_ENCODE_DATA_TYPE = "EncodeDataType"; private static final String KEY_ENCODE_KEY_TYPE = "EncodeKeyType"; /***/ XCryptor mCryptor = new XCryptor(); @Override public void sendAsyncResult(String result) { } @Override public boolean isAsync(String action) { return true; } @Override public XExtensionResult exec(String action, JSONArray args, XCallbackContext callbackCtx) throws JSONException { XExtensionResult.Status status = XExtensionResult.Status.OK; String result = "Unsupported Operation: " + action; try { if (action.equals(COMMAND_ENCRYPT)) { result = encrypt(args.getString(0), args.getString(1), args.optJSONObject(2)); } else if (action.equals(COMMAND_DECRYPT)) { result = decrypt(args.getString(0), args.getString(1), args.optJSONObject(2)); } else if (action.equals(COMMAND_ENCRYPT_FILE)) { result = encryptFile(mWebContext, args.getString(0), args.getString(1), args.getString(2)); } else if (action.equals(COMMAND_DECRYPT_FILE)) { result = decryptFile(mWebContext, args.getString(0), args.getString(1), args.getString(2)); } else if (action.equals(COMMAND_DIGEST)) { result = digest(args.getString(0)); } else { status = XExtensionResult.Status.INVALID_ACTION; } return new XExtensionResult(status, result); } catch (IllegalArgumentException e) { e.printStackTrace(); return new XExtensionResult(XExtensionResult.Status.ERROR, PATH_ERR); } catch (FileNotFoundException e) { e.printStackTrace(); XLog.e(CLASS_NAME, FILE_NOT_FOUND_ERROR, e); return new XExtensionResult(XExtensionResult.Status.ERROR, FILE_NOT_FOUND_ERR); } catch (XCryptionException e) { e.printStackTrace(); XLog.e(CLASS_NAME, CRYPTION_ERROR, e); return new XExtensionResult(XExtensionResult.Status.ERROR, OPERATION_ERR); } } /** * * * @param sKey * * @param sourceData * ?? * @param options * ? * @return ?? */ private String encrypt(String sKey, String sourceData, JSONObject options) throws XCryptionException { int cryptAlgorithm = DES_ALOGRITHEM; int encodeDataType = ENCODE_TYPE_STRING; int encodeKeyType = ENCODE_TYPE_STRING; if (options != null) { cryptAlgorithm = options.optInt(KEY_CRYPT_ALGORITHM, DES_ALOGRITHEM); encodeDataType = options.optInt(KEY_ENCODE_DATA_TYPE, ENCODE_TYPE_BASE64); encodeKeyType = options.optInt(KEY_ENCODE_KEY_TYPE, ENCODE_TYPE_STRING); } byte[] keyBytes = null; keyBytes = getBytesEncode(encodeKeyType, sKey); switch (cryptAlgorithm) { case TRIPLE_DES_ALOGRITHEM: switch (encodeDataType) { case ENCODE_TYPE_HEX: return XStringUtils.hexEncode(mCryptor.encryptBytesFor3DES(sourceData.getBytes(), keyBytes)); default: return XBase64.encodeToString((mCryptor.encryptBytesFor3DES(sourceData.getBytes(), keyBytes)), XBase64.NO_WRAP); } case RSA_ALOGRITHEM: switch (encodeDataType) { case ENCODE_TYPE_HEX: return XStringUtils.hexEncode(mCryptor.encryptRSA(sourceData.getBytes(), keyBytes)); default: return XBase64.encodeToString((mCryptor.encryptRSA(sourceData.getBytes(), keyBytes)), XBase64.NO_WRAP); } default: switch (encodeDataType) { case ENCODE_TYPE_HEX: return XStringUtils.hexEncode(mCryptor.encryptBytesForDES(sourceData.getBytes(), keyBytes)); default: return XBase64.encodeToString((mCryptor.encryptBytesForDES(sourceData.getBytes(), keyBytes)), XBase64.NO_WRAP); } } } /** * * * @param webContext * * @param sKey * * @param sourceFilePath * ??? * @param targetFilePath * ? * @return ? * @throws XCryptionException * @throws FileNotFoundException */ private String encryptFile(XIWebContext webContext, String sKey, String sourceFilePath, String targetFilePath) throws FileNotFoundException, XCryptionException { return doFileCrypt(webContext, sKey, sourceFilePath, targetFilePath, true); } /** * * * @param sKey * * @param sourceData * ?? * @param options * ? * @return ?? */ private String decrypt(String sKey, String sourceData, JSONObject options) throws XCryptionException { int cryptAlgorithm = DES_ALOGRITHEM; int encodeDataType = ENCODE_TYPE_STRING; int encodeKeyType = ENCODE_TYPE_STRING; if (options != null) { cryptAlgorithm = options.optInt(KEY_CRYPT_ALGORITHM, DES_ALOGRITHEM); encodeDataType = options.optInt(KEY_ENCODE_DATA_TYPE, ENCODE_TYPE_STRING); encodeKeyType = options.optInt(KEY_ENCODE_KEY_TYPE, ENCODE_TYPE_STRING); } byte[] keyBytes = null; keyBytes = getBytesEncode(encodeKeyType, sKey); switch (cryptAlgorithm) { case TRIPLE_DES_ALOGRITHEM: switch (encodeDataType) { case ENCODE_TYPE_HEX: return new String(mCryptor.decryptBytesFor3DES(XStringUtils.hexDecode(sourceData), keyBytes)); default: return new String( mCryptor.decryptBytesFor3DES(XBase64.decode(sourceData, XBase64.NO_WRAP), keyBytes)); } case RSA_ALOGRITHEM: switch (encodeDataType) { case ENCODE_TYPE_HEX: return new String(mCryptor.decryptRSA(XStringUtils.hexDecode(sourceData), keyBytes)); default: return new String(mCryptor.decryptRSA(XBase64.decode(sourceData, XBase64.NO_WRAP), keyBytes)); } default: switch (encodeDataType) { case ENCODE_TYPE_HEX: return new String(mCryptor.decryptBytesForDES(XStringUtils.hexDecode(sourceData), keyBytes)); default: return new String( mCryptor.decryptBytesForDES(XBase64.decode(sourceData, XBase64.NO_WRAP), keyBytes)); } } } /** * * * @param webContext * * @param sKey * * @param sourceFilePath * ?(??) * @param targetFilePath * ? * @return ? * @throws FileNotFoundException */ private String decryptFile(XIWebContext webContext, String sKey, String sourceFilePath, String targetFilePath) throws XCryptionException, FileNotFoundException { return doFileCrypt(webContext, sKey, sourceFilePath, targetFilePath, false); } private String doFileCrypt(XIWebContext webContext, String sKey, String sourceFilePath, String targetFilePath, boolean isEncrypt) throws XCryptionException, FileNotFoundException { // ?key if (XStringUtils.isEmptyString(sKey)) { XLog.e(CLASS_NAME, KEY_EMPTY_ERROR); throw new XCryptionException(KEY_EMPTY_ERROR); } // ? if (XStringUtils.isEmptyString(targetFilePath) || XStringUtils.isEmptyString(sourceFilePath)) { throw new IllegalArgumentException(); } // ?? String appWorkSpace = webContext.getWorkSpace(); File sourceFile = new File(appWorkSpace, sourceFilePath); String absSourceFilePath = getAbsFilePath(sourceFile); if ((null == absSourceFilePath) || !XFileUtils.isFileAncestorOf(appWorkSpace, absSourceFilePath)) { throw new IllegalArgumentException(); } if (!sourceFile.exists()) { throw new FileNotFoundException(); } // ???? File targetFile = new File(appWorkSpace, targetFilePath); String absTargetFilePath = getAbsFilePath(targetFile); if (null == absTargetFilePath || !XFileUtils.isFileAncestorOf(appWorkSpace, absTargetFilePath) || (null == new XPathResolver(targetFilePath, appWorkSpace).resolve())) { throw new IllegalArgumentException(); } if (targetFile.exists()) { targetFile.delete(); } if (!XFileUtils.createFile(absTargetFilePath)) { throw new FileNotFoundException(); } byte[] keyBytes = getBytesEncode(ENCODE_TYPE_STRING, sKey); if (isEncrypt ? mCryptor.encryptFileForDES(keyBytes, absSourceFilePath, absTargetFilePath) : mCryptor.decryptFileForDES(keyBytes, absSourceFilePath, absTargetFilePath)) { return targetFilePath; } throw new XCryptionException(CRYPTION_ERROR); } private String digest(String data) { XCryptor cryptor = new XCryptor(); try { return cryptor.calMD5Value(data.getBytes("UTF-8")); } catch (UnsupportedEncodingException e) { XLog.e(CLASS_NAME, "digest failed: UnsupportedEncodingException"); e.printStackTrace(); } return null; } /** * ?? * @param targetFile * @return */ private String getAbsFilePath(File targetFile) throws IllegalArgumentException { try { return targetFile.getCanonicalPath(); } catch (IOException e) { throw new IllegalArgumentException(); } } /** * ????keyBytes * @param encodeKeyType:? * @param keyString :??keyString * @return ?? */ private byte[] getBytesEncode(int encodeKeyType, String keyString) { if (XStringUtils.isEmptyString(keyString)) { return null; } switch (encodeKeyType) { case ENCODE_TYPE_BASE64: return XBase64.decode(keyString, XBase64.NO_WRAP); case ENCODE_TYPE_HEX: return XStringUtils.hexDecode(keyString); default: return keyString.getBytes(); } } }