com.polyvi.xface.extension.XSecurityExt.java Source code

Java tutorial

Introduction

Here is the source code for com.polyvi.xface.extension.XSecurityExt.java

Source

/*
 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();
        }
    }
}