/** * This file Copyright (c) 2005-2008 Aptana, Inc. This program is * dual-licensed under both the Aptana Public License and the GNU General * Public license. You may elect to use one or the other of these licenses. * * This program is distributed in the hope that it will be useful, but * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or * NONINFRINGEMENT. Redistribution, except as permitted by whichever of * the GPL or APL you select, is prohibited. * * 1. For the GPL license (GPL), you can redistribute and/or modify this * program under the terms of the GNU General Public License, * Version 3, as published by the Free Software Foundation. You should * have received a copy of the GNU General Public License, Version 3 along * with this program; if not, write to the Free Software Foundation, Inc., 51 * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Aptana provides a special exception to allow redistribution of this file * with certain Eclipse Public Licensed code and certain additional terms * pursuant to Section 7 of the GPL. You may view the exception and these * terms on the web at http://www.aptana.com/legal/gpl/. * * 2. For the Aptana Public License (APL), this program and the * accompanying materials are made available under the terms of the APL * v1.0 which accompanies this distribution, and is available at * http://www.aptana.com/legal/apl/. * * You may view the GPL, Aptana's exception and additional terms, and the * APL in the file titled license.html at the root of the corresponding * plugin containing this source file. * * Any modifications to this file must keep this entire header intact. */ package com.aptana.rdt.profiling; import java.math.BigInteger; import java.util.Calendar; import java.util.TimeZone; import java.util.zip.CRC32; /** * DO NOT EDIT THIS FILE * * @author Contact Kevin Sawicki (ksawicki@aptana.com) or Ingo Muschenetz (ingo@aptana.com) for details */ /** * Client Key */ public final class ClientKey { /** * BEGIN_LICENSE_MARKER */ public static final String BEGIN_LICENSE_MARKER = "--begin-aptana-license--"; /** * END_LICENSE_MARKER */ public static final String END_LICENSE_MARKER = "--end-aptana-license--"; // private static final Pattern EMAIL_PATTERN = Pattern // .compile("^[a-zA-Z0-9\\!\\#\\$\\%\\&\\'\\*\\+\\-\\/\\=\\?\\^\\_\\`\\{\\|\\}\\~]+(\\.[a-zA-Z0-9\\!\\#\\$\\%\\&\\'\\*\\+\\-\\/\\=\\?\\^\\_\\`\\{\\|\\}\\~])*@[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(\\.[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*\\.[a-zA-Z]{2,6}$"); private static final TimeZone GMT = TimeZone.getTimeZone("GMT"); private static final String EMAILS_NON_MATCHING = "EMAILS_NON_MATCHING"; private static final int PRO = 0; private static final int TRIAL = 1; private String email; private long expiration; private int type; private ClientKey(int type, String email, long expiration) { this.type = type; this.email = email; this.expiration = expiration; } /** * Decrypts an encrypted key string * * @param encrypted * @param email * @return client key */ public static ClientKey decrypt(String encrypted, String email) { // Public Keys // Key Pair 1 - 1024 bits String modulus = "115801190261221214754334668902722425936509505416457970789287297728816388753627896293249501578830570324705253515546383166989625001335561947096747210280001245977114030627247212292377290543869343996595819188362915644707269064020812435233012510929338706599216007185654748959001143012936618501934698642942289379979"; String exponent = "65537"; // Key Pair 2 - 512 bits // String modulus = // "7161565172885831980647861120279411120958785711339417901210739422288321094397693927782833643808877128760462895064358542798826171057389792795593008266372799"; // String exponent = "65537"; if (encrypted != null) { encrypted = encrypted.trim(); } Decrypt decrypter = new Decrypt(exponent, modulus); return decrypt(decrypter, encrypted, email); } private static ClientKey decrypt(Decrypt decrypter, String encrypted, String email) { String value = decrypter.decrypt(encrypted); if (value == null) { return new ClientKey(TRIAL, null, 0L); } String[] values = value.split(";"); int type = TRIAL; String genedEmail = null; long expiration = 0L; if (values.length == 3) { if ("p".equals(values[0].toLowerCase())) { type = PRO; } genedEmail = values[1]; // Verify decrypted email against entered email if (genedEmail != null) { if (!genedEmail.equalsIgnoreCase(email)) { genedEmail = EMAILS_NON_MATCHING; } } else { genedEmail = null; } try { expiration = Long.parseLong(values[2]); } catch (Exception e) { expiration = 0L; } } return new ClientKey(type, genedEmail, expiration); } /** * True if this key is close to expiring * * @return true if close, false otherwise */ public boolean isCloseToExpiring() { Calendar currentCalendar = Calendar.getInstance(ClientKey.GMT); currentCalendar.add(Calendar.MONTH, 1); return getExpiration().before(currentCalendar); } /** * True if valid key * * @return true if valid, false otherwise */ public boolean isValid() { return email != null && email != EMAILS_NON_MATCHING; } /** * True if key has valid fields but email did not match * * @return - true if close, false otherwise */ public boolean isCloseToMatching() { return email == EMAILS_NON_MATCHING; } /** * True if this key is expired * * @return true if expired, false otherwise */ public boolean isExpired() { Calendar currentCalendar = Calendar.getInstance(GMT); return currentCalendar.after(getExpiration()); } /** * Gets the email for this key * * @return - email */ public String getEmail() { return email; } /** * Gets the expiration of this key * * @return - calendar */ public Calendar getExpiration() { Calendar expirationCal = Calendar.getInstance(GMT); expirationCal.setTimeInMillis(expiration); return expirationCal; } /** * True if trial key * * @return true if trial, false otherwise */ public boolean isTrial() { return type == TRIAL; } /** * True if pro key * * @return true if pro, false otherwise */ public boolean isPro() { return !isTrial(); } /** * True if professional plugins should run * * @return true to run pros, false otherwise */ public boolean shouldProPluginsRun() { if (isPro()) { return true; } return !isExpired(); } /** * Gets the trimmed version of a license key * * @param encrypted * @return - trimmed key */ public static String trimEncryptedLicense(String encrypted) { String newEncrypted = encrypted; newEncrypted = newEncrypted.trim(); newEncrypted = newEncrypted.replaceAll(BEGIN_LICENSE_MARKER, ""); newEncrypted = newEncrypted.replaceAll(END_LICENSE_MARKER, ""); newEncrypted = newEncrypted.replaceAll("\\s+", ""); return newEncrypted; } /** * Internal decrypting class */ private static class Decrypt { private BigInteger modulus; private BigInteger exponent; Decrypt(String exponent, String modulus) { this.modulus = new BigInteger(modulus); this.exponent = new BigInteger(exponent); } /** * Decrypts an encrypted string * * @param encrypted * @return - decrypted string */ public String decrypt(String encrypted) { try { if (encrypted == null) { encrypted = ""; } else { encrypted = trimEncryptedLicense(encrypted); } BigInteger big = new BigInteger(encrypted); BigInteger decrypted = big.modPow(exponent, modulus); long crc32Value = ((long) decrypted.intValue()) & 0xffffffffL; decrypted = decrypted.shiftRight(32); byte[] bytes = decrypted.toByteArray(); CRC32 crc32 = new CRC32(); crc32.update(bytes); if (crc32Value == crc32.getValue()) { return new String(bytes); } } catch (NumberFormatException e) { } return null; } } /** * TODO add later to call from command line * * @param args */ // public static void main(String[] args) // { // if (args.length == 2) // { // String email = args[0]; // String key = args[1]; // } // } }