com.screenslicer.common.Crypto.java Source code

Java tutorial

Introduction

Here is the source code for com.screenslicer.common.Crypto.java

Source

/* 
 * ScreenSlicer (TM) -- automatic, zero-config web scraping (TM)
 * Copyright (C) 2013-2014 Machine Publishers, LLC
 * ops@machinepublishers.com | screenslicer.com | machinepublishers.com
 * 717 Martin Luther King Dr W Ste I, Cincinnati, Ohio 45220
 *
 * You can redistribute this program and/or modify it under the terms of the
 * GNU Affero General Public License version 3 as published by the Free
 * Software Foundation. Additional permissions or commercial licensing may be
 * available--see LICENSE file or contact Machine Publishers, LLC for details.
 * 
 * This program 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 Affero General Public License version 3
 * for more details.
 * 
 * You should have received a copy of the GNU Affero General Public License
 * version 3 along with this program. If not, see <http://www.gnu.org/licenses/>.
 * 
 * For general details about how to investigate and report license violations,
 * please see: https://www.gnu.org/licenses/gpl-violation.html
 * and email the author: ops@machinepublishers.com
 * Keep in mind that paying customers have more rights than the AGPL alone offers.
 */
package com.screenslicer.common;

import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.digest.DigestUtils;

import com.google.gson.reflect.TypeToken;

public class Crypto {
    private static final Type stringType = new TypeToken<Map<String, String>>() {
    }.getType();
    private static String secretA = Config.instance.secretA();
    private static String secretB = Config.instance.secretB();
    private static String secretC = Config.instance.secretC();
    private static String secretD = Config.instance.secretD();
    private static Map<String, Long> usedTokens = new HashMap<String, Long>();
    private static final Object lock = new Object();
    private static final long EXPIRE = 10 * 60 * 1000;

    private static Map<String, String> asMap(String... keysAndVals) {
        HashMap<String, String> map = new HashMap<String, String>();
        int mid = keysAndVals.length / 2;
        for (int i = 0; i < mid; i++) {
            map.put(keysAndVals[i], keysAndVals[i + mid]);
        }
        return map;
    }

    public static String fastHash(String str) {
        try {
            return new String(DigestUtils.sha256Hex(str));
        } catch (Exception e) {
            Log.exception(e);
            throw new RuntimeException(e);
        }
    }

    public static int fastHashInt(String str) {
        try {
            return str.hashCode();
        } catch (Exception e) {
            Log.exception(e);
            throw new RuntimeException(e);
        }
    }

    private static void push(String token, long time) {
        synchronized (lock) {
            long curTime = System.currentTimeMillis();
            List<String> toRemove = new ArrayList<String>();
            for (Map.Entry<String, Long> usedToken : usedTokens.entrySet()) {
                if (curTime - usedToken.getValue() > EXPIRE) {
                    toRemove.add(usedToken.getKey());
                }
            }
            for (String key : toRemove) {
                usedTokens.remove(key);
            }
            usedTokens.put(token, time);
        }
    }

    private static long validateTime(String token, String time) {
        if (token == null) {
            return 0;
        }
        try {
            if (time == null || time.indexOf(secretD) != 0) {
                return 0;
            }
            long authTime = Long.parseLong(time.substring(secretD.length()));
            if (System.currentTimeMillis() - authTime > EXPIRE) {
                return 0;
            }
            synchronized (lock) {
                return !usedTokens.containsKey(token) ? authTime : 0;
            }
        } catch (Exception e) {
            Log.exception(e);
            return 0;
        }
    }

    private static String getKey(String token, String auth, String recipient) {
        if (token == null || auth == null || recipient == null) {
            return null;
        }
        try {
            String newKey = createKey(token, recipient);
            String str = decodeHelper(auth, newKey);
            long time = validateTime(token, str);
            if (time != 0) {
                push(token, time);
                return newKey;
            }
            return null;
        } catch (Exception e) {
            Log.exception(e);
        }
        return null;
    }

    private static String createAuth(String secretKey) {
        return encodeHelper(secretD + System.currentTimeMillis(), secretKey);
    }

    private static String createKey(String token, String recipient) {
        return new String(recipient + secretA + token);
    }

    public static String encode(String string, String recipient) {
        if (string == null || recipient == null) {
            return null;
        }
        String token = Random.next();
        String secretKey = createKey(token, recipient);
        String auth = createAuth(secretKey);
        String message = encodeHelper(string, secretKey);
        return CommonUtil.gson.toJson(asMap("auth", "token", "message", auth, token, message), stringType);
    }

    public static String encode(String string) {
        if (string == null) {
            return null;
        }
        String secretKey = createKey(secretB, secretC);
        return "encodedv1:" + encodeHelper(string, secretKey);
    }

    public static String decode(String string) {
        if (CommonUtil.isEmpty(string)) {
            return null;
        }
        if (string.startsWith("encodedv1:")) {
            String secretKey = createKey(secretB, secretC);
            return decodeHelper(string.substring("encodedv1:".length()), secretKey);
        }
        return string;
    }

    public static String decode(String string, String recipient) {
        if (CommonUtil.isEmpty(string)) {
            return null;
        }
        Map<String, String> map = CommonUtil.gson.fromJson(string, stringType);
        String secretKey = getKey(map.get("token"), map.get("auth"), recipient);
        if (secretKey == null) {
            return null;
        }
        return decodeHelper(map.get("message"), secretKey);
    }

    private static String encodeHelper(String plainText, String encryptionKey) {
        if (plainText == null || encryptionKey == null) {
            return null;
        }
        try {
            Cipher aesCipher = Cipher.getInstance("AES");
            aesCipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(DigestUtils.sha256(encryptionKey), "AES"));
            return Base64.encodeBase64String(aesCipher.doFinal(plainText.getBytes("utf-8")));
        } catch (Exception e) {
            return null;
        }
    }

    private static String decodeHelper(String cipherText, String encryptionKey) {
        if (cipherText == null || encryptionKey == null) {
            return null;
        }
        try {
            Cipher aesCipher = Cipher.getInstance("AES");
            aesCipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(DigestUtils.sha256(encryptionKey), "AES"),
                    aesCipher.getParameters());
            return new String(aesCipher.doFinal(Base64.decodeBase64(cipherText)), "utf-8");
        } catch (Exception e) {
            return null;
        }
    }
}