diff --git a/.classpath b/.classpath new file mode 100644 index 0000000000000000000000000000000000000000..534b5e52fa500e767d4a3828d9dfd636f3729853 --- /dev/null +++ b/.classpath @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..e2a3069b6ee98740d149140b881d6947483653c9 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +/target +*~ diff --git a/license/.project b/.project similarity index 61% rename from license/.project rename to .project index 9c4301f36027b7235c5b3daf0ea3479da671b2fc..e38c98b21a50321e887fcf719044c539d9c9c66f 100644 --- a/license/.project +++ b/.project @@ -1,6 +1,6 @@ - license + com.patrikdufresne.license @@ -10,8 +10,14 @@ + + org.eclipse.m2e.core.maven2Builder + + + org.eclipse.jdt.core.javanature + org.eclipse.m2e.core.maven2Nature diff --git a/.settings/org.eclipse.jdt.core.prefs b/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000000000000000000000000000000000000..60105c1b9516ec7dc540970605e57f7ffe09e368 --- /dev/null +++ b/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,5 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 +org.eclipse.jdt.core.compiler.compliance=1.6 +org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning +org.eclipse.jdt.core.compiler.source=1.6 diff --git a/.settings/org.eclipse.m2e.core.prefs b/.settings/org.eclipse.m2e.core.prefs new file mode 100644 index 0000000000000000000000000000000000000000..f897a7f1cb2389f85fe6381425d29f0a9866fb65 --- /dev/null +++ b/.settings/org.eclipse.m2e.core.prefs @@ -0,0 +1,4 @@ +activeProfiles= +eclipse.preferences.version=1 +resolveWorkspaceProjects=true +version=1 diff --git a/license/Apache b/LICENSE similarity index 100% rename from license/Apache rename to LICENSE diff --git a/license/README b/README similarity index 56% rename from license/README rename to README index c906d39e4bde3e1b0e3d36f6d60cbc7c93fb23bb..79aafd0bc42006eb07842f7b1d8c5878927753de 100644 --- a/license/README +++ b/README @@ -1,25 +1,13 @@ -Copyright (c) 2012 David Stites, Patrik Dufresne and others. +Copyright (c) 2013 David Stites, Patrik Dufresne and others. LICENSING ========= This program is free software; you can redistribute it and/or modify -it under the terms of either: - - a) The MIT License (MIT) - - b) Apache License 2.0 - - c) Simplified BSD License +it under the terms of Apache License 2.0 -You should have received a copy of the MIT License (MIT) with this -software, in the file named "MIT". If not, I'll be glad to provide one. - You should have received a copy of the Apache License 2.0 -along with this program in the file named "Apache". - -You should have received a copy of the Simplified BSD License -along with this program in the file named "BSD". +along with this program in the file named "LICENSE". This package is based on the following article: http://blog.afewguyscoding.com/2012/02/licensing-module-java/ diff --git a/license/.classpath b/license/.classpath deleted file mode 100644 index 18d70f02cb8eeded3bb20b75f0cd29bb66157990..0000000000000000000000000000000000000000 --- a/license/.classpath +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/license/.gitignore b/license/.gitignore deleted file mode 100644 index a65a85e96bd7fa720e9d1d493b5b24053b8d007f..0000000000000000000000000000000000000000 --- a/license/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -/ant-target -/bin diff --git a/license/.settings/org.eclipse.jdt.core.prefs b/license/.settings/org.eclipse.jdt.core.prefs deleted file mode 100644 index 906a73619e0e06633aaf44d283b8b1f721a2a967..0000000000000000000000000000000000000000 --- a/license/.settings/org.eclipse.jdt.core.prefs +++ /dev/null @@ -1,12 +0,0 @@ -#Tue Apr 03 18:41:31 EDT 2012 -eclipse.preferences.version=1 -org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 -org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve -org.eclipse.jdt.core.compiler.compliance=1.6 -org.eclipse.jdt.core.compiler.debug.lineNumber=generate -org.eclipse.jdt.core.compiler.debug.localVariable=generate -org.eclipse.jdt.core.compiler.debug.sourceFile=generate -org.eclipse.jdt.core.compiler.problem.assertIdentifier=error -org.eclipse.jdt.core.compiler.problem.enumIdentifier=error -org.eclipse.jdt.core.compiler.source=1.6 diff --git a/license/BSD b/license/BSD deleted file mode 100644 index 79684c5c313344b7b295f82b8c4a184fc7c8c2ad..0000000000000000000000000000000000000000 --- a/license/BSD +++ /dev/null @@ -1,24 +0,0 @@ - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -1. Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. -2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -The views and conclusions contained in the software and documentation are those -of the authors and should not be interpreted as representing official policies, -either expressed or implied, of the FreeBSD Project. \ No newline at end of file diff --git a/license/MIT b/license/MIT deleted file mode 100644 index 4d644be563e69d755031dd6e71a76ece3dd14875..0000000000000000000000000000000000000000 --- a/license/MIT +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2012 - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies -of the Software, and to permit persons to whom the Software is furnished to do -so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. \ No newline at end of file diff --git a/license/build.xml b/license/build.xml deleted file mode 100644 index e8393ffefc155de04f6a78f2d14d69866924b26b..0000000000000000000000000000000000000000 --- a/license/build.xml +++ /dev/null @@ -1,55 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/license/src/com/patrikdufresne/license/AbstractLicense.java b/license/src/com/patrikdufresne/license/AbstractLicense.java deleted file mode 100644 index 57d4f87ebdf016879f93b428a91a6ae78175bf0d..0000000000000000000000000000000000000000 --- a/license/src/com/patrikdufresne/license/AbstractLicense.java +++ /dev/null @@ -1,233 +0,0 @@ -/* - * Copyright (c) 2012 David Stites, Patrik Dufresne and others. - * - * You may distribute under the terms of either the MIT License, the Apache - * License 2.0 or the Simplified BSD License, as specified in the README file. - * - * Contributors: - * David Stites - initial API and implementation - * Patrik Dufresne - refactoring - */ -package com.patrikdufresne.license; - -import java.io.Serializable; -import java.util.Date; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * Abstract implementation of the license interface use by the license manager. - * - * @author Patrik Dufresne - * - */ -public abstract class AbstractLicense implements Serializable, ILicense { - - private static final long serialVersionUID = -144058457108187374L; - - /** - * License type for lifetime version. Always valid. - */ - public static final String TYPE_LIFETIME = "lifetime"; - /** - * License type for single version. This type is valid for the given - * version. - */ - public static final String TYPE_SINGLE_VERSION = "single-version"; - /** - * License type for trial version. This type is valid until the expiration - * date. - */ - public static final String TYPE_TRIAL = "trial"; - - private String email; - - private Date expiration; - - private String licenseNumber; - - private String licenseType; - private String name; - private String version; - - /** - * Create a new license with default property value. - */ - public AbstractLicense() { - name = ""; - email = ""; - licenseNumber = ""; - expiration = new Date(); - version = ""; - licenseType = TYPE_TRIAL; - } - - /** - * Return the associated email value. - * - * @return the email or null - */ - public String getEmail() { - return email; - } - - /** - * @return the expiration - */ - public Date getExpiration() { - return expiration; - } - - /** - * @return the licenseNumber - */ - public String getLicenseNumber() { - return licenseNumber; - } - - /** - * Return the license type. - * - * @return the licenseType - */ - public String getLicenseType() { - return licenseType; - } - - /** - * Return the name associated with the license. - * - * @return the name or null - */ - public String getName() { - return name; - } - - /** - * Return the license version - * - * @return the version or null - */ - public String getVersion() { - return version; - } - - /** - * Sets the associated email - * - * @param email - * the email or null. - */ - public void setEmail(String email) { - this.email = email; - } - - /** - * Set the license expiration date. Required with TYPE_TRIAL - * - * @param expiration - * the expiration date or null. - */ - public void setExpiration(Date expiration) { - this.expiration = expiration; - } - - /** - * Sets the license number. - * - * @param licenseNumber - * the licenseNumber - */ - public void setLicenseNumber(String licenseNumber) { - this.licenseNumber = licenseNumber; - } - - /** - * Sets the license type. - * - * @param licenseType - * the licenseType, one of the TYPE_* constants (can't be null). - */ - public void setLicenseType(String licenseType) { - if (licenseType == null) { - throw new NullPointerException(); - } - this.licenseType = licenseType; - } - - /** - * Sets the name associated with the license - * - * @param name - * the name or null - */ - public void setName(String name) { - this.name = name; - } - - /** - * Sets the license version. Required with SINGLE_VERSION. - * - * @param version - * the version or null - */ - public void setVersion(String version) { - this.version = version; - } - - /** - * Check if the given license object is valid. - * - * @param license - * the license object - */ - public void validate(Date currentDate, String currentVersion) - throws LicenseException { - - validateExpiration(new Date()); - - validateVersion(currentVersion); - - } - - /** - * Used to validate the expiration date according to the license type. - * - * @param currentDate - * the current date. - * @throws LicenseExpiredException - */ - protected void validateExpiration(Date currentDate) - throws LicenseExpiredException { - if (getLicenseType().equals(TYPE_TRIAL)) { - if (getExpiration() == null || currentDate.after(getExpiration())) { - throw new LicenseExpiredException(); - } - } - // The expiration date doesn't matter for a single version license or a - // lifetime version. - } - - /** - * Used to validate the version according to the license type. - * - * @param currentVersion - * @throws LicenseVersionExpiredException - */ - protected void validateVersion(String currentVersion) - throws LicenseVersionExpiredException { - - if (getLicenseType().equals(TYPE_SINGLE_VERSION)) { - if (getVersion() == null) { - throw new LicenseVersionExpiredException(); - } - Pattern pattern = Pattern.compile(getVersion()); - Matcher matcher = pattern.matcher(currentVersion); - if (!matcher.matches()) { - throw new LicenseVersionExpiredException(); - } - } - - } - -} diff --git a/license/src/com/patrikdufresne/license/EncryptionManager.java b/license/src/com/patrikdufresne/license/EncryptionManager.java deleted file mode 100644 index 6282ab7677f26f813ec5ecf2d4e012c18257c867..0000000000000000000000000000000000000000 --- a/license/src/com/patrikdufresne/license/EncryptionManager.java +++ /dev/null @@ -1,197 +0,0 @@ -/* - * Copyright (c) 2012 David Stites, Patrik Dufresne and others. - * - * You may distribute under the terms of either the MIT License, the Apache - * License 2.0 or the Simplified BSD License, as specified in the README file. - * - * Contributors: - * David Stites - initial API and implementation - * Patrik Dufresne - refactoring - */ -package com.patrikdufresne.license; - -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.security.InvalidKeyException; -import java.security.KeyFactory; -import java.security.NoSuchAlgorithmException; -import java.security.NoSuchProviderException; -import java.security.PrivateKey; -import java.security.PublicKey; -import java.security.Signature; -import java.security.SignatureException; -import java.security.spec.InvalidKeySpecException; -import java.security.spec.PKCS8EncodedKeySpec; -import java.security.spec.X509EncodedKeySpec; - -/** - * This class is used to manage the encryption of the license. It's used to - * encrypt, sign and validate using a public or private key. - * - * @author Patrik Dufresne - * - */ -public class EncryptionManager { - - private static final int SIZE = 2048; - - /** - * Single instance of the utility class. - */ - // private static EncryptionManager instance; - - // private static final String PUBLIC_KEY_FILE = "/License/public_key.der"; - - // private static final String PRIVATE_KEY_FILE = - // "/path/to/your/private_key.der"; - - private PublicKey publicKey; - - /** - * Our private key. - */ - private PrivateKey privateKey; - - /** - * Create a new encryption manager. - * - * @param publicKey - * the public key (can't be null). - * @param privateKey - * the private key (null if not available). - * @throws NoSuchAlgorithmException - * if no Provider supports RSA - * @throws InvalidKeySpecException - * if the given key specification is inappropriate for this key - * factory to produce a public key. - */ - public EncryptionManager(byte[] publicKey, byte[] privateKey) - throws NoSuchAlgorithmException, InvalidKeySpecException { - if (publicKey == null) { - throw new NullPointerException("publicKey"); - } - - X509EncodedKeySpec spec = new X509EncodedKeySpec(publicKey); - KeyFactory kf = KeyFactory.getInstance("RSA"); - this.publicKey = kf.generatePublic(spec); - - if (privateKey != null) { - PKCS8EncodedKeySpec privateSpec = new PKCS8EncodedKeySpec( - privateKey); - KeyFactory privateKeyFactory = KeyFactory.getInstance("RSA"); - this.privateKey = privateKeyFactory.generatePrivate(privateSpec); - } - - } - - /** - * This function is used to read a stream. - * - * @param input - * the input stream - * @return the data read from the stream - * @throws IOException - */ - public static byte[] readAll(InputStream input) throws IOException { - // Read the content of the file and store it in a byte array. - ByteArrayOutputStream out = new ByteArrayOutputStream(SIZE); - byte[] buf = new byte[SIZE]; - int size; - while ((size = input.read(buf)) != -1) { - out.write(buf, 0, size); - } - return out.toByteArray(); - } - - /** - * This function maybe used to read the public and/or private key from a - * file. - * - * @param file - * the file to read - * @return the file data - * - * @throws IOException - * if the file does not exist, or if the first byte cannot be - * read for any reason - */ - public static byte[] readAll(File file) throws IOException { - InputStream input = new FileInputStream(file); - try { - return readAll(input); - } finally { - input.close(); - } - } - - /** - * Use to check if the given data matches the given signature. - * - * @param data - * the data - * @param sig - * the signature associated with the data. - * - * @throws NoSuchAlgorithmException - * if the algorithm SHA1withRSA is not supported. - * @throws NoSuchProviderException - * @throws InvalidKeyException - * if the key is invalid. - * @throws SignatureException - * if this signature algorithm is unable to process the input - * data - */ - public boolean verify(byte[] data, byte[] sig) - throws NoSuchAlgorithmException, InvalidKeyException, - SignatureException { - - // Initialize the signing algorithm with our public key - Signature rsaSignature = Signature.getInstance("SHA1withRSA"); - rsaSignature.initVerify(publicKey); - - // Update the signature algorithm with the data. - rsaSignature.update(data); - - // Validate the signature - return rsaSignature.verify(sig); - - } - - /** - * Sign the given input stream data. The signature is append to the output - * stream. - * - * @param data - * the the data to be signed. - * @return the signature for the given data. - * @throws NoSuchAlgorithmException - * if no Provider supports a Signature implementation for - * SHA1withRSA. - * @throws InvalidKeyException - * if the private key is invalid. - * @throws SignatureException - * if this signature algorithm is unable to process the input - * data provided. - * @throws UnsupportedOperationException - * if the private key was not providedin the constructor. - */ - public byte[] sign(byte[] data) throws NoSuchAlgorithmException, - InvalidKeyException, SignatureException { - if (privateKey == null) { - throw new UnsupportedOperationException( - "Can't sign when the private key is not available."); - } - - // Initialize the signing algorithm with our private key - Signature rsaSignature = Signature.getInstance("SHA1withRSA"); - rsaSignature.initSign(privateKey); - rsaSignature.update(data); - - // Generate the signature. - return rsaSignature.sign(); - - } -} diff --git a/license/src/com/patrikdufresne/license/ILicense.java b/license/src/com/patrikdufresne/license/ILicense.java deleted file mode 100644 index 5bd3f43ef4200ef26c7d1fa1ff79d2270067cb79..0000000000000000000000000000000000000000 --- a/license/src/com/patrikdufresne/license/ILicense.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright (c) 2012 David Stites, Patrik Dufresne and others. - * - * You may distribute under the terms of either the MIT License, the Apache - * License 2.0 or the Simplified BSD License, as specified in the README file. - * - * Contributors: - * David Stites - initial API and implementation - * Patrik Dufresne - refactoring - */ -package com.patrikdufresne.license; - -import java.io.Serializable; - -/** - * This interface is used to represent a license data. - * - * @author ikus060 - * - */ -public interface ILicense extends Serializable { - -} diff --git a/license/src/com/patrikdufresne/license/KeyBlackListedException.java b/license/src/com/patrikdufresne/license/KeyBlackListedException.java deleted file mode 100644 index 7942b5c8f0c6c463d25e0bef26587a597b0dfc82..0000000000000000000000000000000000000000 --- a/license/src/com/patrikdufresne/license/KeyBlackListedException.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (c) 2012 David Stites, Patrik Dufresne and others. - * - * You may distribute under the terms of either the MIT License, the Apache - * License 2.0 or the Simplified BSD License, as specified in the README file. - * - * Contributors: - * David Stites - initial API and implementation - * Patrik Dufresne - refactoring - */ -package com.patrikdufresne.license; - -/** - * This exception is throw by the key manager when the key is determined to be - * black listed. - * - * @author Patrik Dufresne - * - */ -public class KeyBlackListedException extends LicenseException { - - private static final long serialVersionUID = 4833729281645719038L; - - public KeyBlackListedException() { - super("black listed key"); - } -} diff --git a/license/src/com/patrikdufresne/license/KeyInvalidException.java b/license/src/com/patrikdufresne/license/KeyInvalidException.java deleted file mode 100644 index 5445214584bf568acbd92cdddb14bf0e503e1f2d..0000000000000000000000000000000000000000 --- a/license/src/com/patrikdufresne/license/KeyInvalidException.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (c) 2012 David Stites, Patrik Dufresne and others. - * - * You may distribute under the terms of either the MIT License, the Apache - * License 2.0 or the Simplified BSD License, as specified in the README file. - * - * Contributors: - * David Stites - initial API and implementation - * Patrik Dufresne - refactoring - */ -package com.patrikdufresne.license; - -/** - * This exception is throw when the key manager determine the key as invalid - * because of the checksum or because it's been wrongly generated. - * - * @author Patrik Dufresne - * - */ -public class KeyInvalidException extends LicenseException { - - private static final long serialVersionUID = 3455646784833396158L; - - public KeyInvalidException() { - super("invalid key"); - } -} diff --git a/license/src/com/patrikdufresne/license/KeyManager.java b/license/src/com/patrikdufresne/license/KeyManager.java deleted file mode 100644 index 3da04eb3d58f220c65c81a96dc214ded58a6237c..0000000000000000000000000000000000000000 --- a/license/src/com/patrikdufresne/license/KeyManager.java +++ /dev/null @@ -1,365 +0,0 @@ -/* - * Copyright (c) 2012 David Stites, Patrik Dufresne and others. - * - * You may distribute under the terms of either the MIT License, the Apache - * License 2.0 or the Simplified BSD License, as specified in the README file. - * - * Contributors: - * David Stites - initial API and implementation - * Patrik Dufresne - refactoring - */ -package com.patrikdufresne.license; - -import java.net.InetAddress; -import java.net.NetworkInterface; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; -import java.util.HashSet; -import java.util.Set; - -/** - * This class is useful to generate key to identify a specific hardware using - * the network card. - * - * @author Patrik Dufresne - * - */ -public class KeyManager { - /** - * Define the default key length. - */ - private static final int DEFAULT_KEY_LENGTH = 62; - - /** - * Defin the default default mac address. - */ - private static final byte[] DEFAULT_MAC_ADRESS = new byte[] { 24, 4, 124, - 10, 91 }; - private static final byte[][] DEFAULT_PARAMS = new byte[][] { - { 24, 4, 127 }, { 10, 0, 56 }, { 1, 2, 91 }, { 7, 1, 100 } }; - - /** - * Calculate a checksum. - * - * @param string - * @return the check sum value - */ - private static String calculateChecksum(final String string) { - int left = 0x0056; - int right = 0x00AF; - for (byte b : string.getBytes()) { - right += b; - if (right > 0x00FF) { - right -= 0x00FF; - } - left += right; - if (left > 0x00FF) { - left -= 0x00FF; - } - } - int sum = (left << 8) + right; - return intToHex(sum, 4); - } - - /** - * Get the key bytes. - * - * @param seed - * @param a - * @param b - * @param c - * @return - */ - private static byte getKeyByte(final int seed, final byte a, final byte b, - final byte c) { - final int a1 = a % 25; - final int b1 = b % 3; - if (a1 % 2 == 0) { - return (byte) (((seed >> a1) & 0x000000FF) ^ ((seed >> b1) | c)); - } else { - return (byte) (((seed >> a1) & 0x000000FF) ^ ((seed >> b1) & c)); - } - - } - - /** - * - * @param n - * @param chars - * @return - */ - private static String intToHex(final Number n, final int chars) { - return String.format("%0" + chars + "x", n); - } - - /** - * Sets of black listed keys. - */ - private Set blacklist; - - /** - * Default MAC address if no network interface is available. - */ - private byte[] defaultMac; - - /** - * The current key length. - */ - private int keyLen; - - /** - * Arrays used to generate and validate the key. - */ - private byte[][] params; - - public KeyManager() { - this(DEFAULT_KEY_LENGTH, DEFAULT_PARAMS, DEFAULT_MAC_ADRESS); - } - - /** - * - * @param keyLen - * the key length (>=8); - * @param params - * @param defaultMacAddress - * used if no network interface is available - * - */ - public KeyManager(int keyLen, byte[][] params, byte[] defaultMacAddress) { - if (keyLen < 8) { - throw new IllegalArgumentException("keyLen<8"); - } - this.keyLen = keyLen; - - this.params = params; - - this.defaultMac = defaultMacAddress; - - } - - /** - * Ass the given key to the black list. - * - * @param key - * the key to be added - */ - public void addBlackListedKey(String key) { - if (this.blacklist == null) { - this.blacklist = new HashSet(); - } - this.blacklist.add(key); - } - - /** - * - * @param seed - * @param entropy - * @return - */ - public String generateKey(final int seed, String authCode) { - - byte[] entropy = getHardwareEntropy(); - - final byte[] keyBytes = new byte[25]; - // fill keyBytes with values derived from seed. - // the parameters used here must be exactly the same - // as the ones used in the checkKey function. - keyBytes[0] = getKeyByte(seed, params[0][0], params[0][1], params[0][2]); - keyBytes[1] = getKeyByte(seed, params[1][0], params[1][1], params[1][2]); - keyBytes[2] = getKeyByte(seed, params[2][0], params[2][1], params[2][2]); - keyBytes[3] = getKeyByte(seed, params[3][0], params[3][1], params[3][2]); - for (int i = 4, j = 0; (j + 2) < entropy.length; i++, j += 3) { - keyBytes[i] = getKeyByte(seed, entropy[j], entropy[j + 1], - entropy[j + 2]); - } - - // The key string begins with a hexadecimal string of the seed - final StringBuilder result = new StringBuilder(intToHex(seed, 8)); - - // Then is followed by hexadecimal strings of each byte in the key - for (byte b : keyBytes) { - result.append(intToHex(b, 2)); - } - - // Add checksum to key string - String key = result.toString(); - key += calculateChecksum(key); - - return key; - } - - /** - * Return the complete list of blackl listed key. - * - * @return - */ - public String[] getBlackListedKeys() { - if (this.blacklist == null) { - return new String[0]; - } - String[] list = new String[this.blacklist.size()]; - return this.blacklist.toArray(list); - } - - /** - * Generate an hardate entropy based on the network address. - * - * @return the hardware entropy value. - */ - private byte[] getHardwareEntropy() { - // Get the MAC address value - byte[] mac; - try { - NetworkInterface ni = NetworkInterface.getByInetAddress(InetAddress - .getLocalHost()); - if (ni != null) { - mac = ni.getHardwareAddress(); - if (mac == null) { - mac = defaultMac; - } - } else { - mac = defaultMac; - } - } catch (Exception ex) { - mac = defaultMac; - } - - // Hash the value - byte[] entropyEncoded = null; - try { - MessageDigest digest = MessageDigest.getInstance("SHA-512"); - digest.reset(); - entropyEncoded = digest.digest(mac); - } catch (NoSuchAlgorithmException ex) { /* this will never happen */ - } - - return entropyEncoded; - } - - /** - * Remove the given key from the black list. - * - * @param key - * the key to remove. - */ - public void removeBlackListedKey(String key) { - if (this.blacklist != null) { - this.blacklist.remove(key); - if (this.blacklist.size() == 0) { - this.blacklist = null; - } - } - } - - /** - * Check if a key is valid. - * - * @param key - * the key to validate - * @throws KeyInvalidException - * if the key is invalid - */ - public void validateKey(final String key) throws KeyInvalidException, - KeyBlackListedException { - // Validate the key checksum - if (!validateKeyChecksum(key)) { - throw new KeyInvalidException(); - } - - // Look at the black list. - if (this.blacklist != null) { - for (String black : this.blacklist) { - if (key.startsWith(black)) { - throw new KeyBlackListedException(); - } - } - } - - // At this point, the key is either valid or forged, - // because a forged key can have a valid checksum. - // we now test the "bytes" of the key to determine if it is - // actually valid. - - // When building your release application, use conditional defines - // or comment out most of the byte checks! this is the heart - // of the partial key verification system. by not compiling in - // each check, there is no way for someone to build a keygen that - // will produce valid keys. if an invalid keygen is released, you can - // simply change which byte checks are compiled in, and any serial - // number built with the fake keygen no longer works. - - // note that the parameters used for getKeyByte calls MUST - // MATCH the values that makeKey uses to make the key in the - // first place! - - // Extract the seed from the supplied key string - final int seed; - try { - seed = Integer.valueOf(key.substring(0, 8), 16); - } catch (NumberFormatException e) { - throw new KeyInvalidException(); - } - - // test key 0 - final String kb0 = key.substring(8, 10); - final byte b0 = getKeyByte(seed, params[0][0], params[0][1], - params[0][2]); - if (!kb0.equals(intToHex(b0, 2))) { - throw new KeyInvalidException(); - } - - // test key1 - final String kb1 = key.substring(10, 12); - final byte b1 = getKeyByte(seed, params[1][0], params[1][1], - params[1][2]); - if (!kb1.equals(intToHex(b1, 2))) { - throw new KeyInvalidException(); - } - - // test key2 - final String kb2 = key.substring(12, 14); - final byte b2 = getKeyByte(seed, params[2][0], params[2][1], - params[2][2]); - if (!kb2.equals(intToHex(b2, 2))) { - throw new KeyInvalidException(); - } - - // test key3 - final String kb3 = key.substring(14, 16); - final byte b3 = getKeyByte(seed, params[3][0], params[3][1], - params[3][2]); - if (!kb3.equals(intToHex(b3, 2))) { - throw new KeyInvalidException(); - } - - // test the hardware entropy - byte[] encodedEntropy = getHardwareEntropy(); - for (int i = 16, j = 0; (j + 2) < encodedEntropy.length; i += 2, j += 3) { - String kb = key.substring(i, i + 2); - byte b = getKeyByte(seed, encodedEntropy[j], encodedEntropy[j + 1], - encodedEntropy[j + 2]); - if (!kb.equals(intToHex(b, 2))) { - throw new KeyInvalidException(); - } - } - - } - - /** - * Validate the key check sum. - * - * @param key - * the key value - * @return - */ - private boolean validateKeyChecksum(final String key) { - if (key.length() != this.keyLen) { - throw new IllegalArgumentException("key wrong length"); - } - // last four characters are the checksum - final String checksum = key.substring(this.keyLen - 4); - return checksum.equals(calculateChecksum(key.substring(0, - this.keyLen - 4))); - } - -} diff --git a/license/src/com/patrikdufresne/license/LicenseException.java b/license/src/com/patrikdufresne/license/LicenseException.java deleted file mode 100644 index 76c58c3c1ff8cea3321dc4ef2b40726c0ee710c9..0000000000000000000000000000000000000000 --- a/license/src/com/patrikdufresne/license/LicenseException.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (c) 2012 David Stites, Patrik Dufresne and others. - * - * You may distribute under the terms of either the MIT License, the Apache - * License 2.0 or the Simplified BSD License, as specified in the README file. - * - * Contributors: - * David Stites - initial API and implementation - * Patrik Dufresne - refactoring - */ -package com.patrikdufresne.license; - -/** - * - * This exception regroup all the license exceptions. - * - * @author Patrik Dufresne - * - */ -public class LicenseException extends Exception { - - private static final long serialVersionUID = 7895696254570225320L; - - /** - * Constructs a new exception with null as its detail message. The cause is - * not initialized, and may subsequently be initialized by a call to - * Throwable.initCause(java.lang.Throwable). - */ - public LicenseException() { - this(null, null); - } - - /** - * Constructs a new exception with the specified message. - * - * @param message - * the detail message (which is saved for later retrieval by the - * Throwable.getMessage() method). - */ - public LicenseException(String message) { - this(message, null); - } - - /** - * Constructs a new exception with the specified cause. - * - * @param cause - * the cause (which is saved for later retrieval by the - * Throwable.getCause() method). (A null value is permitted, and - * indicates that the cause is nonexistent or unknown.) - */ - public LicenseException(Throwable cause) { - this(null, cause); - } - - /** - * Constructs a new exception with the specified detail message and cause. - * - * @param message - * the detail message (which is saved for later retrieval by the - * Throwable.getMessage() method). - * @param cause - * the cause (which is saved for later retrieval by the - * Throwable.getCause() method). (A null value is permitted, and - * indicates that the cause is nonexistent or unknown.) - */ - public LicenseException(String message, Throwable cause) { - super(message, cause); - } - -} diff --git a/license/src/com/patrikdufresne/license/LicenseExpiredException.java b/license/src/com/patrikdufresne/license/LicenseExpiredException.java deleted file mode 100644 index a7d7e86778a36e0e9c6126b96a3a52409254ace1..0000000000000000000000000000000000000000 --- a/license/src/com/patrikdufresne/license/LicenseExpiredException.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (c) 2012 David Stites, Patrik Dufresne and others. - * - * You may distribute under the terms of either the MIT License, the Apache - * License 2.0 or the Simplified BSD License, as specified in the README file. - * - * Contributors: - * David Stites - initial API and implementation - * Patrik Dufresne - refactoring - */ -package com.patrikdufresne.license; - -/** - * Thrown when the license validation determine the license to be expired. The - * expiration date should then by retrieve using the - * {@link AbstractLicense#getExpiration()}. - * - * @author Patrik Dufresne - * - */ -public class LicenseExpiredException extends LicenseException { - - private static final long serialVersionUID = -9069804052012922999L; - - /** - * Constructs a new exception with null as its detail message. The cause is - * not initialized, and may subsequently be initialized by a call to - * Throwable.initCause(java.lang.Throwable). - */ - public LicenseExpiredException() { - super("license expired"); - } - -} diff --git a/license/src/com/patrikdufresne/license/LicenseManager.java b/license/src/com/patrikdufresne/license/LicenseManager.java deleted file mode 100644 index f8c30b61eb9a6c62582d2ce5677719b0458f5025..0000000000000000000000000000000000000000 --- a/license/src/com/patrikdufresne/license/LicenseManager.java +++ /dev/null @@ -1,232 +0,0 @@ -/* - * Copyright (c) 2012 David Stites, Patrik Dufresne and others. - * - * You may distribute under the terms of either the MIT License, the Apache - * License 2.0 or the Simplified BSD License, as specified in the README file. - * - * Contributors: - * David Stites - initial API and implementation - * Patrik Dufresne - refactoring - */ -package com.patrikdufresne.license; - -import java.io.BufferedInputStream; -import java.io.BufferedOutputStream; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; -import java.security.GeneralSecurityException; -import java.security.InvalidKeyException; -import java.security.NoSuchAlgorithmException; -import java.security.SignatureException; - -/** - * This the main entry point of the licensing module. This class should be used - * to create and check license files. - *

- * Generally, an application will not required more then one instance of license - * manager. - * - * @author Patrik Dufresne - * - */ -public class LicenseManager { - private static final int SIZE = 2048; - /** - * The encryption manager used by this class.F - */ - private EncryptionManager encryptionManager; - - /** - * Create a new license manager. - * - * @param publicKey - * the public key filename. - * @param privateKey - * the private key filename (null if not available). - * @throws GeneralSecurityException - * if the provided key are invalid. - * @throws IOException - * if the file doesn't exists - */ - public LicenseManager(String publicKey, String privateKey) - throws GeneralSecurityException, IOException { - byte[] pubdata = EncryptionManager.readAll(new File(publicKey)); - byte[] privdata = null; - if (privateKey != null) { - privdata = EncryptionManager.readAll(new File(privateKey)); - } - this.encryptionManager = new EncryptionManager(pubdata, privdata); - } - - /** - * Create a new license manager. - * - * @param publicKey - * the public key file. - * @param privateKey - * the private key file (null if not available). - * @throws GeneralSecurityException - * if the provided key are invalid. - * @throws IOException - * if the file doesn't exists - */ - public LicenseManager(File publicKey, File privateKey) - throws GeneralSecurityException, IOException { - byte[] pubdata = EncryptionManager.readAll(publicKey); - byte[] privdata = null; - if (privateKey != null) { - privdata = EncryptionManager.readAll(privateKey); - } - this.encryptionManager = new EncryptionManager(pubdata, privdata); - } - - /** - * Create a new license manager. - * - * @param publicKey - * an input stream containing the public key - * @param privateKey - * an input stream containing the private key - */ - public LicenseManager(InputStream publicKey, InputStream privateKey) - throws GeneralSecurityException, IOException { - byte[] pubdata = EncryptionManager.readAll(publicKey); - byte[] privdata = null; - if (privateKey != null) { - privdata = EncryptionManager.readAll(privateKey); - } - this.encryptionManager = new EncryptionManager(pubdata, privdata); - } - - /** - * Create a new license manager. Generally, an application will not required - * more then one instance of license manager. - * - * @param publicKey - * the public key (can't be null). - * - * @param privateKey - * the private key (null if not available). - * @throws GeneralSecurityException - * if the provided key are invalid. - */ - public LicenseManager(byte[] publicKey, byte[] privateKey) - throws GeneralSecurityException { - this.encryptionManager = new EncryptionManager(publicKey, privateKey); - } - - /** - * Read the content of an encrypted license file. - * - * @param file - * the location to the license file. - * @return the license object if the license file is valid, null otherwise. - * @throws IOException - * if file not found or read error. - * @throws SignatureException - * if this signature algorithm is unable to process the content - * of the file - * @throws NoSuchAlgorithmException - * if the SHA algorithm doesn't exists - * @throws InvalidKeyException - * if the public key is invalid - * @throws ClassNotFoundException - * if the implementation of {@link ILicense} stored in the file - * can't be found - */ - public ILicense readLicenseFile(File file) throws IOException, - InvalidKeyException, NoSuchAlgorithmException, SignatureException, - ClassNotFoundException { - - // Read the content of the file - byte[] sig; - byte[] data; - ObjectInputStream fileIn = new ObjectInputStream( - new BufferedInputStream(new FileInputStream(file))); - try { - int sigLength = fileIn.readInt(); - sig = new byte[sigLength]; - fileIn.read(sig); - - ByteArrayOutputStream dataStream = new ByteArrayOutputStream(); - byte[] buf = new byte[SIZE]; - int len; - while ((len = fileIn.read(buf)) != -1) { - dataStream.write(buf, 0, len); - } - dataStream.flush(); - data = dataStream.toByteArray(); - dataStream.close(); - } finally { - fileIn.close(); - } - - // Validate the signature - if (!encryptionManager.verify(data, sig)) { - return null; - } - - // Read the license object from the data. - ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream( - data)); - try { - ILicense license = (ILicense) in.readObject(); - return license; - } finally { - in.close(); - } - - } - - /** - * Used to serialize a license object. - * - * @param license - * the license object. - * @param file - * the location where to save the new license file. If file - * exists, it's overwrite. - * @throws IOException - * if the file doesn't exists or can't be written to - * @throws SignatureException - * if this signature algorithm is unable to process the license - * data - * @throws NoSuchAlgorithmException - * if the algorithm SHA is not supported - * @throws InvalidKeyException - * if the private key is invalid. - */ - public void writeLicense(ILicense license, File file) throws IOException, - InvalidKeyException, NoSuchAlgorithmException, SignatureException { - // Write the license information into a byte array. - ByteArrayOutputStream dataStream = new ByteArrayOutputStream(); - ObjectOutputStream out = new ObjectOutputStream(dataStream); - out.writeObject(license); - byte[] data = dataStream.toByteArray(); - out.close(); - - // Then sign the byte array - byte[] signature = this.encryptionManager.sign(data); - - // Write all the data into one single file. - ObjectOutputStream fileOut = new ObjectOutputStream( - new BufferedOutputStream(new FileOutputStream(file))); - try { - fileOut.writeInt(signature.length); - fileOut.write(signature); - fileOut.write(data); - fileOut.flush(); - } finally { - fileOut.close(); - } - - } - -} diff --git a/license/src/com/patrikdufresne/license/LicenseVersionExpiredException.java b/license/src/com/patrikdufresne/license/LicenseVersionExpiredException.java deleted file mode 100644 index 3a53faf92b063095074362a8f6f6447b83848208..0000000000000000000000000000000000000000 --- a/license/src/com/patrikdufresne/license/LicenseVersionExpiredException.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (c) 2012 David Stites, Patrik Dufresne and others. - * - * You may distribute under the terms of either the MIT License, the Apache - * License 2.0 or the Simplified BSD License, as specified in the README file. - * - * Contributors: - * David Stites - initial API and implementation - * Patrik Dufresne - refactoring - */ -package com.patrikdufresne.license; - -/** - * This exception is throw when the license version doesn't match the current - * version. - * - * @author Patrik Dufresne - * - */ -public class LicenseVersionExpiredException extends LicenseException { - - private static final long serialVersionUID = 8947235554238066208L; - - public LicenseVersionExpiredException() { - super("version expired"); - } - -} diff --git a/license/src/com/patrikdufresne/license/util/ILogger.java b/license/src/com/patrikdufresne/license/util/ILogger.java deleted file mode 100644 index 8f4071729d7f120faf40e81ca7bc0b64b7e2d5d1..0000000000000000000000000000000000000000 --- a/license/src/com/patrikdufresne/license/util/ILogger.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (c) 2012 David Stites, Patrik Dufresne and others. - * - * You may distribute under the terms of either the MIT License, the Apache - * License 2.0 or the Simplified BSD License, as specified in the README file. - * - * Contributors: - * David Stites - initial API and implementation - * Patrik Dufresne - refactoring - */ -package com.patrikdufresne.license.util; - -/** - * A mechanism to log errors throughout the license framework. - *

- * Clients may provide their own implementation to change how errors are logged - * from within the license framework. - *

- * - */ -public interface ILogger { - /** - * Trace level (value: trace). - */ - public static final String TRACE = "trace"; - /** - * Debug level (value: debug). - */ - public static final String DEBUG = "debug"; - /** - * Info level (value: info). - */ - public static final String INFO = "info"; - /** - * Warn level (value: warn). - */ - public static final String WARN = "warn"; - /** - * Error level (value: error). - */ - public static final String ERROR = "error"; - - /** - * Logs the given status. - * - * @param level - * The level - * @param message - * The message to be logged. - */ - public void log(String level, String message); - - /** - * Logs the given exception. - * - * @param level - * @param exception - */ - public void log(String level, Throwable exception); - -} diff --git a/license/src/com/patrikdufresne/license/util/Policy.java b/license/src/com/patrikdufresne/license/util/Policy.java deleted file mode 100644 index 00f54b02c712c1c55d9e281f8312e93c10c7f57d..0000000000000000000000000000000000000000 --- a/license/src/com/patrikdufresne/license/util/Policy.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (c) 2012 David Stites, Patrik Dufresne and others. - * - * You may distribute under the terms of either the MIT License, the Apache - * License 2.0 or the Simplified BSD License, as specified in the README file. - * - * Contributors: - * David Stites - initial API and implementation - * Patrik Dufresne - refactoring - */ -package com.patrikdufresne.license.util; - -/** - * The Policy class handles settings for behavior, debug flags and logging - * within the license framework. - * - */ -public class Policy { - - private static ILogger log; - - /** - * Returns the dummy log to use if none has been set - */ - private static ILogger getDummyLog() { - return new ILogger() { - @Override - public void log(String level, String message) { - System.out.print(level + " " + message); - } - - @Override - public void log(String level, Throwable exception) { - exception.printStackTrace(System.out); - } - }; - } - - /** - * Returns the logger used by the license framework to log errors. - *

- * The default logger prints the status to System.err. - *

- * - * @return the logger - */ - public static ILogger getLog() { - if (log == null) { - log = getDummyLog(); - } - return log; - } - - /** - * Sets the logger used by the license framework to log errors. - * - * @param logger - * the logger to use, or null to use the default - * logger - */ - public static void setLog(ILogger logger) { - log = logger; - } - -} diff --git a/license/version.properties b/license/version.properties deleted file mode 100644 index f8f6da16e9aedb934595595adf16cc2dd98e7588..0000000000000000000000000000000000000000 --- a/license/version.properties +++ /dev/null @@ -1,2 +0,0 @@ -version=0.2 -package.name=com.patrikdufresne.license \ No newline at end of file diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000000000000000000000000000000000000..59102bbb8e5d67af5f051f621eb7485407efa120 --- /dev/null +++ b/pom.xml @@ -0,0 +1,130 @@ + + 4.0.0 + com.patrikdufresne.license + com.patrikdufresne.license + 0.3-SNAPSHOT + + + + + + org.eclipse.m2e + lifecycle-mapping + 1.0.0 + + + + + + + com.mycila.maven-license-plugin + + + maven-license-plugin + + + [1.9.0,) + + + format + + + + + + + + + + com.googlecode.maven-java-formatter-plugin + + + maven-java-formatter-plugin + + + [0.3.1,) + + + format + + + + + + + + + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.0 + + 1.6 + 1.6 + + + + + org.apache.maven.plugins + maven-source-plugin + + + attach-sources + + jar + + + + + + + com.googlecode.maven-java-formatter-plugin + maven-java-formatter-plugin + 0.3.1 + + + + format + + + + + src/main/build-tools/formatter.xml + + + + + com.mycila.maven-license-plugin + maven-license-plugin + 1.9.0 + + + process-sources + + format + + + + +
src/main/build-tools/license-header.txt
+
+
+
+
+ + + junit + junit + 4.11 + test + + +
\ No newline at end of file diff --git a/src/main/build-tools/formatter.xml b/src/main/build-tools/formatter.xml new file mode 100644 index 0000000000000000000000000000000000000000..2ce16cf469380f5501ffb01eb5fe1912d0490a3b --- /dev/null +++ b/src/main/build-tools/formatter.xml @@ -0,0 +1,308 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/build-tools/license-header.txt b/src/main/build-tools/license-header.txt new file mode 100644 index 0000000000000000000000000000000000000000..da306b8ed4f6fecfeaa6231d8b0cbc0afe2645ce --- /dev/null +++ b/src/main/build-tools/license-header.txt @@ -0,0 +1,13 @@ +Copyright(C) 2013 Patrik Dufresne Service Logiciel + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. \ No newline at end of file diff --git a/src/main/java/com/patrikdufresne/license/AbstractLicense.java b/src/main/java/com/patrikdufresne/license/AbstractLicense.java new file mode 100644 index 0000000000000000000000000000000000000000..ca1fa1398a7f899c72d65ed681bff3836a8fc8cf --- /dev/null +++ b/src/main/java/com/patrikdufresne/license/AbstractLicense.java @@ -0,0 +1,235 @@ +/** + * Copyright(C) 2013 Patrik Dufresne Service Logiciel + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.patrikdufresne.license; + +import java.io.Serializable; +import java.util.Date; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Abstract implementation of the license interface use by the license manager. + * + * @author Patrik Dufresne + * + */ +public abstract class AbstractLicense implements Serializable, ILicense { + + private static final long serialVersionUID = -144058457108187374L; + + /** + * License type for lifetime version. Always valid. + */ + public static final String TYPE_LIFETIME = "lifetime"; + /** + * License type for single version. This type is valid for the given + * version. + */ + public static final String TYPE_SINGLE_VERSION = "single-version"; + /** + * License type for trial version. This type is valid until the expiration + * date. + */ + public static final String TYPE_TRIAL = "trial"; + + private String email; + + private Date expiration; + + private String licenseNumber; + + private String licenseType; + private String name; + private String version; + + /** + * Create a new license with default property value. + */ + public AbstractLicense() { + name = ""; + email = ""; + licenseNumber = ""; + expiration = new Date(); + version = ""; + licenseType = TYPE_TRIAL; + } + + /** + * Return the associated email value. + * + * @return the email or null + */ + public String getEmail() { + return email; + } + + /** + * @return the expiration + */ + public Date getExpiration() { + return expiration; + } + + /** + * @return the licenseNumber + */ + public String getLicenseNumber() { + return licenseNumber; + } + + /** + * Return the license type. + * + * @return the licenseType + */ + public String getLicenseType() { + return licenseType; + } + + /** + * Return the name associated with the license. + * + * @return the name or null + */ + public String getName() { + return name; + } + + /** + * Return the license version + * + * @return the version or null + */ + public String getVersion() { + return version; + } + + /** + * Sets the associated email + * + * @param email + * the email or null. + */ + public void setEmail(String email) { + this.email = email; + } + + /** + * Set the license expiration date. Required with TYPE_TRIAL + * + * @param expiration + * the expiration date or null. + */ + public void setExpiration(Date expiration) { + this.expiration = expiration; + } + + /** + * Sets the license number. + * + * @param licenseNumber + * the licenseNumber + */ + public void setLicenseNumber(String licenseNumber) { + this.licenseNumber = licenseNumber; + } + + /** + * Sets the license type. + * + * @param licenseType + * the licenseType, one of the TYPE_* constants (can't be null). + */ + public void setLicenseType(String licenseType) { + if (licenseType == null) { + throw new NullPointerException(); + } + this.licenseType = licenseType; + } + + /** + * Sets the name associated with the license + * + * @param name + * the name or null + */ + public void setName(String name) { + this.name = name; + } + + /** + * Sets the license version. Required with SINGLE_VERSION. + * + * @param version + * the version or null + */ + public void setVersion(String version) { + this.version = version; + } + + /** + * Check if the given license object is valid. + * + * @param license + * the license object + */ + public void validate(Date currentDate, String currentVersion) throws LicenseException { + + validateExpiration(new Date()); + + validateVersion(currentVersion); + + } + + /** + * Used to validate the expiration date according to the license type. + * + * @param currentDate + * the current date. + * @throws LicenseExpiredException + */ + protected void validateExpiration(Date currentDate) throws LicenseExpiredException { + if (getLicenseType().equals(TYPE_TRIAL)) { + if (getExpiration() == null || currentDate.after(getExpiration())) { + throw new LicenseExpiredException(); + } + } + // The expiration date doesn't matter for a single version license or a + // lifetime version. + } + + /** + * Used to validate the version according to the license type. + * + * @param currentVersion + * @throws LicenseVersionExpiredException + */ + protected void validateVersion(String currentVersion) throws LicenseVersionExpiredException { + + if (getLicenseType().equals(TYPE_SINGLE_VERSION)) { + if (getVersion() == null) { + throw new LicenseVersionExpiredException(); + } + Pattern pattern = Pattern.compile(getVersion()); + Matcher matcher = pattern.matcher(currentVersion); + if (!matcher.matches()) { + throw new LicenseVersionExpiredException(); + } + } + + } + +} diff --git a/src/main/java/com/patrikdufresne/license/EncryptionManager.java b/src/main/java/com/patrikdufresne/license/EncryptionManager.java new file mode 100644 index 0000000000000000000000000000000000000000..fb180631f32e951b6f2aa56bc46b0e46d4335ca5 --- /dev/null +++ b/src/main/java/com/patrikdufresne/license/EncryptionManager.java @@ -0,0 +1,196 @@ +/** + * Copyright(C) 2013 Patrik Dufresne Service Logiciel + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.patrikdufresne.license; + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.security.InvalidKeyException; +import java.security.KeyFactory; +import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; +import java.security.PrivateKey; +import java.security.PublicKey; +import java.security.Signature; +import java.security.SignatureException; +import java.security.spec.InvalidKeySpecException; +import java.security.spec.PKCS8EncodedKeySpec; +import java.security.spec.X509EncodedKeySpec; + +/** + * This class is used to manage the encryption of the license. It's used to + * encrypt, sign and validate using a public or private key. + * + * @author Patrik Dufresne + * + */ +public class EncryptionManager { + + private static final int SIZE = 2048; + + /** + * Single instance of the utility class. + */ + // private static EncryptionManager instance; + + // private static final String PUBLIC_KEY_FILE = "/License/public_key.der"; + + // private static final String PRIVATE_KEY_FILE = + // "/path/to/your/private_key.der"; + + private PublicKey publicKey; + + /** + * Our private key. + */ + private PrivateKey privateKey; + + /** + * Create a new encryption manager. + * + * @param publicKey + * the public key (can't be null). + * @param privateKey + * the private key (null if not available). + * @throws NoSuchAlgorithmException + * if no Provider supports RSA + * @throws InvalidKeySpecException + * if the given key specification is inappropriate for this key + * factory to produce a public key. + */ + public EncryptionManager(byte[] publicKey, byte[] privateKey) throws NoSuchAlgorithmException, InvalidKeySpecException { + if (publicKey == null) { + throw new NullPointerException("publicKey"); + } + + X509EncodedKeySpec spec = new X509EncodedKeySpec(publicKey); + KeyFactory kf = KeyFactory.getInstance("RSA"); + this.publicKey = kf.generatePublic(spec); + + if (privateKey != null) { + PKCS8EncodedKeySpec privateSpec = new PKCS8EncodedKeySpec(privateKey); + KeyFactory privateKeyFactory = KeyFactory.getInstance("RSA"); + this.privateKey = privateKeyFactory.generatePrivate(privateSpec); + } + + } + + /** + * This function is used to read a stream. + * + * @param input + * the input stream + * @return the data read from the stream + * @throws IOException + */ + public static byte[] readAll(InputStream input) throws IOException { + // Read the content of the file and store it in a byte array. + ByteArrayOutputStream out = new ByteArrayOutputStream(SIZE); + byte[] buf = new byte[SIZE]; + int size; + while ((size = input.read(buf)) != -1) { + out.write(buf, 0, size); + } + return out.toByteArray(); + } + + /** + * This function maybe used to read the public and/or private key from a + * file. + * + * @param file + * the file to read + * @return the file data + * + * @throws IOException + * if the file does not exist, or if the first byte cannot be + * read for any reason + */ + public static byte[] readAll(File file) throws IOException { + InputStream input = new FileInputStream(file); + try { + return readAll(input); + } finally { + input.close(); + } + } + + /** + * Use to check if the given data matches the given signature. + * + * @param data + * the data + * @param sig + * the signature associated with the data. + * + * @throws NoSuchAlgorithmException + * if the algorithm SHA1withRSA is not supported. + * @throws NoSuchProviderException + * @throws InvalidKeyException + * if the key is invalid. + * @throws SignatureException + * if this signature algorithm is unable to process the input + * data + */ + public boolean verify(byte[] data, byte[] sig) throws NoSuchAlgorithmException, InvalidKeyException, SignatureException { + + // Initialize the signing algorithm with our public key + Signature rsaSignature = Signature.getInstance("SHA1withRSA"); + rsaSignature.initVerify(publicKey); + + // Update the signature algorithm with the data. + rsaSignature.update(data); + + // Validate the signature + return rsaSignature.verify(sig); + + } + + /** + * Sign the given input stream data. The signature is append to the output + * stream. + * + * @param data + * the the data to be signed. + * @return the signature for the given data. + * @throws NoSuchAlgorithmException + * if no Provider supports a Signature implementation for + * SHA1withRSA. + * @throws InvalidKeyException + * if the private key is invalid. + * @throws SignatureException + * if this signature algorithm is unable to process the input + * data provided. + * @throws UnsupportedOperationException + * if the private key was not providedin the constructor. + */ + public byte[] sign(byte[] data) throws NoSuchAlgorithmException, InvalidKeyException, SignatureException { + if (privateKey == null) { + throw new UnsupportedOperationException("Can't sign when the private key is not available."); + } + + // Initialize the signing algorithm with our private key + Signature rsaSignature = Signature.getInstance("SHA1withRSA"); + rsaSignature.initSign(privateKey); + rsaSignature.update(data); + + // Generate the signature. + return rsaSignature.sign(); + + } +} diff --git a/src/main/java/com/patrikdufresne/license/ILicense.java b/src/main/java/com/patrikdufresne/license/ILicense.java new file mode 100644 index 0000000000000000000000000000000000000000..2f3cff3ad0ec63de3586d838fb73b671f39c5444 --- /dev/null +++ b/src/main/java/com/patrikdufresne/license/ILicense.java @@ -0,0 +1,28 @@ +/** + * Copyright(C) 2013 Patrik Dufresne Service Logiciel + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.patrikdufresne.license; + +import java.io.Serializable; + +/** + * This interface is used to represent a license data. + * + * @author ikus060 + * + */ +public interface ILicense extends Serializable { + +} diff --git a/src/main/java/com/patrikdufresne/license/KeyBlackListedException.java b/src/main/java/com/patrikdufresne/license/KeyBlackListedException.java new file mode 100644 index 0000000000000000000000000000000000000000..cde1831bfe290ba3876863cf3318918f0235b749 --- /dev/null +++ b/src/main/java/com/patrikdufresne/license/KeyBlackListedException.java @@ -0,0 +1,32 @@ +/** + * Copyright(C) 2013 Patrik Dufresne Service Logiciel + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.patrikdufresne.license; + +/** + * This exception is throw by the key manager when the key is determined to be + * black listed. + * + * @author Patrik Dufresne + * + */ +public class KeyBlackListedException extends LicenseException { + + private static final long serialVersionUID = 4833729281645719038L; + + public KeyBlackListedException() { + super("black listed key"); + } +} diff --git a/src/main/java/com/patrikdufresne/license/KeyInvalidException.java b/src/main/java/com/patrikdufresne/license/KeyInvalidException.java new file mode 100644 index 0000000000000000000000000000000000000000..5bc1361fbd63b802d67084b842ab512d504dca19 --- /dev/null +++ b/src/main/java/com/patrikdufresne/license/KeyInvalidException.java @@ -0,0 +1,32 @@ +/** + * Copyright(C) 2013 Patrik Dufresne Service Logiciel + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.patrikdufresne.license; + +/** + * This exception is throw when the key manager determine the key as invalid + * because of the checksum or because it's been wrongly generated. + * + * @author Patrik Dufresne + * + */ +public class KeyInvalidException extends LicenseException { + + private static final long serialVersionUID = 3455646784833396158L; + + public KeyInvalidException() { + super("invalid key"); + } +} diff --git a/src/main/java/com/patrikdufresne/license/KeyManager.java b/src/main/java/com/patrikdufresne/license/KeyManager.java new file mode 100644 index 0000000000000000000000000000000000000000..d2f9341baca073014591863b1a79f2499f7abd46 --- /dev/null +++ b/src/main/java/com/patrikdufresne/license/KeyManager.java @@ -0,0 +1,358 @@ +/** + * Copyright(C) 2013 Patrik Dufresne Service Logiciel + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.patrikdufresne.license; + +import java.net.InetAddress; +import java.net.NetworkInterface; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.HashSet; +import java.util.Set; + +/** + * This class is useful to generate key to identify a specific hardware using + * the network card. + * + * @author Patrik Dufresne + * + */ +public class KeyManager { + /** + * Define the default key length. + */ + private static final int DEFAULT_KEY_LENGTH = 62; + + /** + * Defin the default default mac address. + */ + private static final byte[] DEFAULT_MAC_ADRESS = new byte[] { 24, 4, 124, 10, 91 }; + private static final byte[][] DEFAULT_PARAMS = new byte[][] { { 24, 4, 127 }, { 10, 0, 56 }, { 1, 2, 91 }, { 7, 1, 100 } }; + + /** + * Calculate a checksum. + * + * @param string + * @return the check sum value + */ + private static String calculateChecksum(final String string) { + int left = 0x0056; + int right = 0x00AF; + for (byte b : string.getBytes()) { + right += b; + if (right > 0x00FF) { + right -= 0x00FF; + } + left += right; + if (left > 0x00FF) { + left -= 0x00FF; + } + } + int sum = (left << 8) + right; + return intToHex(sum, 4); + } + + /** + * Get the key bytes. + * + * @param seed + * @param a + * @param b + * @param c + * @return + */ + private static byte getKeyByte(final int seed, final byte a, final byte b, final byte c) { + final int a1 = a % 25; + final int b1 = b % 3; + if (a1 % 2 == 0) { + return (byte) (((seed >> a1) & 0x000000FF) ^ ((seed >> b1) | c)); + } else { + return (byte) (((seed >> a1) & 0x000000FF) ^ ((seed >> b1) & c)); + } + + } + + /** + * + * @param n + * @param chars + * @return + */ + private static String intToHex(final Number n, final int chars) { + return String.format("%0" + chars + "x", n); + } + + /** + * Sets of black listed keys. + */ + private Set blacklist; + + /** + * Default MAC address if no network interface is available. + */ + private byte[] defaultMac; + + /** + * The current key length. + */ + private int keyLen; + + /** + * Arrays used to generate and validate the key. + */ + private byte[][] params; + + public KeyManager() { + this(DEFAULT_KEY_LENGTH, DEFAULT_PARAMS, DEFAULT_MAC_ADRESS); + } + + /** + * + * @param keyLen + * the key length (>=8); + * @param params + * @param defaultMacAddress + * used if no network interface is available + * + */ + public KeyManager(int keyLen, byte[][] params, byte[] defaultMacAddress) { + if (keyLen < 8) { + throw new IllegalArgumentException("keyLen<8"); + } + this.keyLen = keyLen; + + this.params = params; + + this.defaultMac = defaultMacAddress; + + } + + /** + * Ass the given key to the black list. + * + * @param key + * the key to be added + */ + public void addBlackListedKey(String key) { + if (this.blacklist == null) { + this.blacklist = new HashSet(); + } + this.blacklist.add(key); + } + + /** + * + * @param seed + * @param entropy + * @return + */ + public String generateKey(final int seed, String authCode) { + + byte[] entropy = getHardwareEntropy(); + + final byte[] keyBytes = new byte[25]; + // fill keyBytes with values derived from seed. + // the parameters used here must be exactly the same + // as the ones used in the checkKey function. + keyBytes[0] = getKeyByte(seed, params[0][0], params[0][1], params[0][2]); + keyBytes[1] = getKeyByte(seed, params[1][0], params[1][1], params[1][2]); + keyBytes[2] = getKeyByte(seed, params[2][0], params[2][1], params[2][2]); + keyBytes[3] = getKeyByte(seed, params[3][0], params[3][1], params[3][2]); + for (int i = 4, j = 0; (j + 2) < entropy.length; i++, j += 3) { + keyBytes[i] = getKeyByte(seed, entropy[j], entropy[j + 1], entropy[j + 2]); + } + + // The key string begins with a hexadecimal string of the seed + final StringBuilder result = new StringBuilder(intToHex(seed, 8)); + + // Then is followed by hexadecimal strings of each byte in the key + for (byte b : keyBytes) { + result.append(intToHex(b, 2)); + } + + // Add checksum to key string + String key = result.toString(); + key += calculateChecksum(key); + + return key; + } + + /** + * Return the complete list of blackl listed key. + * + * @return + */ + public String[] getBlackListedKeys() { + if (this.blacklist == null) { + return new String[0]; + } + String[] list = new String[this.blacklist.size()]; + return this.blacklist.toArray(list); + } + + /** + * Generate an hardate entropy based on the network address. + * + * @return the hardware entropy value. + */ + private byte[] getHardwareEntropy() { + // Get the MAC address value + byte[] mac; + try { + NetworkInterface ni = NetworkInterface.getByInetAddress(InetAddress.getLocalHost()); + if (ni != null) { + mac = ni.getHardwareAddress(); + if (mac == null) { + mac = defaultMac; + } + } else { + mac = defaultMac; + } + } catch (Exception ex) { + mac = defaultMac; + } + + // Hash the value + byte[] entropyEncoded = null; + try { + MessageDigest digest = MessageDigest.getInstance("SHA-512"); + digest.reset(); + entropyEncoded = digest.digest(mac); + } catch (NoSuchAlgorithmException ex) { /* this will never happen */ + } + + return entropyEncoded; + } + + /** + * Remove the given key from the black list. + * + * @param key + * the key to remove. + */ + public void removeBlackListedKey(String key) { + if (this.blacklist != null) { + this.blacklist.remove(key); + if (this.blacklist.size() == 0) { + this.blacklist = null; + } + } + } + + /** + * Check if a key is valid. + * + * @param key + * the key to validate + * @throws KeyInvalidException + * if the key is invalid + */ + public void validateKey(final String key) throws KeyInvalidException, KeyBlackListedException { + // Validate the key checksum + if (!validateKeyChecksum(key)) { + throw new KeyInvalidException(); + } + + // Look at the black list. + if (this.blacklist != null) { + for (String black : this.blacklist) { + if (key.startsWith(black)) { + throw new KeyBlackListedException(); + } + } + } + + // At this point, the key is either valid or forged, + // because a forged key can have a valid checksum. + // we now test the "bytes" of the key to determine if it is + // actually valid. + + // When building your release application, use conditional defines + // or comment out most of the byte checks! this is the heart + // of the partial key verification system. by not compiling in + // each check, there is no way for someone to build a keygen that + // will produce valid keys. if an invalid keygen is released, you can + // simply change which byte checks are compiled in, and any serial + // number built with the fake keygen no longer works. + + // note that the parameters used for getKeyByte calls MUST + // MATCH the values that makeKey uses to make the key in the + // first place! + + // Extract the seed from the supplied key string + final int seed; + try { + seed = Integer.valueOf(key.substring(0, 8), 16); + } catch (NumberFormatException e) { + throw new KeyInvalidException(); + } + + // test key 0 + final String kb0 = key.substring(8, 10); + final byte b0 = getKeyByte(seed, params[0][0], params[0][1], params[0][2]); + if (!kb0.equals(intToHex(b0, 2))) { + throw new KeyInvalidException(); + } + + // test key1 + final String kb1 = key.substring(10, 12); + final byte b1 = getKeyByte(seed, params[1][0], params[1][1], params[1][2]); + if (!kb1.equals(intToHex(b1, 2))) { + throw new KeyInvalidException(); + } + + // test key2 + final String kb2 = key.substring(12, 14); + final byte b2 = getKeyByte(seed, params[2][0], params[2][1], params[2][2]); + if (!kb2.equals(intToHex(b2, 2))) { + throw new KeyInvalidException(); + } + + // test key3 + final String kb3 = key.substring(14, 16); + final byte b3 = getKeyByte(seed, params[3][0], params[3][1], params[3][2]); + if (!kb3.equals(intToHex(b3, 2))) { + throw new KeyInvalidException(); + } + + // test the hardware entropy + byte[] encodedEntropy = getHardwareEntropy(); + for (int i = 16, j = 0; (j + 2) < encodedEntropy.length; i += 2, j += 3) { + String kb = key.substring(i, i + 2); + byte b = getKeyByte(seed, encodedEntropy[j], encodedEntropy[j + 1], encodedEntropy[j + 2]); + if (!kb.equals(intToHex(b, 2))) { + throw new KeyInvalidException(); + } + } + + } + + /** + * Validate the key check sum. + * + * @param key + * the key value + * @return + */ + private boolean validateKeyChecksum(final String key) { + if (key.length() != this.keyLen) { + throw new IllegalArgumentException("key wrong length"); + } + // last four characters are the checksum + final String checksum = key.substring(this.keyLen - 4); + return checksum.equals(calculateChecksum(key.substring(0, this.keyLen - 4))); + } + +} diff --git a/src/main/java/com/patrikdufresne/license/LicenseException.java b/src/main/java/com/patrikdufresne/license/LicenseException.java new file mode 100644 index 0000000000000000000000000000000000000000..ca5a012939a8a160f81f21806b0ac64d58e086dc --- /dev/null +++ b/src/main/java/com/patrikdufresne/license/LicenseException.java @@ -0,0 +1,76 @@ +/** + * Copyright(C) 2013 Patrik Dufresne Service Logiciel + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.patrikdufresne.license; + +/** + * + * This exception regroup all the license exceptions. + * + * @author Patrik Dufresne + * + */ +public class LicenseException extends Exception { + + private static final long serialVersionUID = 7895696254570225320L; + + /** + * Constructs a new exception with null as its detail message. The cause is + * not initialized, and may subsequently be initialized by a call to + * Throwable.initCause(java.lang.Throwable). + */ + public LicenseException() { + this(null, null); + } + + /** + * Constructs a new exception with the specified message. + * + * @param message + * the detail message (which is saved for later retrieval by the + * Throwable.getMessage() method). + */ + public LicenseException(String message) { + this(message, null); + } + + /** + * Constructs a new exception with the specified cause. + * + * @param cause + * the cause (which is saved for later retrieval by the + * Throwable.getCause() method). (A null value is permitted, and + * indicates that the cause is nonexistent or unknown.) + */ + public LicenseException(Throwable cause) { + this(null, cause); + } + + /** + * Constructs a new exception with the specified detail message and cause. + * + * @param message + * the detail message (which is saved for later retrieval by the + * Throwable.getMessage() method). + * @param cause + * the cause (which is saved for later retrieval by the + * Throwable.getCause() method). (A null value is permitted, and + * indicates that the cause is nonexistent or unknown.) + */ + public LicenseException(String message, Throwable cause) { + super(message, cause); + } + +} diff --git a/src/main/java/com/patrikdufresne/license/LicenseExpiredException.java b/src/main/java/com/patrikdufresne/license/LicenseExpiredException.java new file mode 100644 index 0000000000000000000000000000000000000000..307458d2fd357df2908da8f091281a66a4ea8ef6 --- /dev/null +++ b/src/main/java/com/patrikdufresne/license/LicenseExpiredException.java @@ -0,0 +1,39 @@ +/** + * Copyright(C) 2013 Patrik Dufresne Service Logiciel + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.patrikdufresne.license; + +/** + * Thrown when the license validation determine the license to be expired. The + * expiration date should then by retrieve using the + * {@link AbstractLicense#getExpiration()}. + * + * @author Patrik Dufresne + * + */ +public class LicenseExpiredException extends LicenseException { + + private static final long serialVersionUID = -9069804052012922999L; + + /** + * Constructs a new exception with null as its detail message. The cause is + * not initialized, and may subsequently be initialized by a call to + * Throwable.initCause(java.lang.Throwable). + */ + public LicenseExpiredException() { + super("license expired"); + } + +} diff --git a/src/main/java/com/patrikdufresne/license/LicenseManager.java b/src/main/java/com/patrikdufresne/license/LicenseManager.java new file mode 100644 index 0000000000000000000000000000000000000000..5a65305b6b6fbd6c6084a11ceb632a32385faca0 --- /dev/null +++ b/src/main/java/com/patrikdufresne/license/LicenseManager.java @@ -0,0 +1,227 @@ +/** + * Copyright(C) 2013 Patrik Dufresne Service Logiciel + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.patrikdufresne.license; + +import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.security.GeneralSecurityException; +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; +import java.security.SignatureException; + +/** + * This the main entry point of the licensing module. This class should be used + * to create and check license files. + *

+ * Generally, an application will not required more then one instance of license + * manager. + * + * @author Patrik Dufresne + * + */ +public class LicenseManager { + private static final int SIZE = 2048; + /** + * The encryption manager used by this class.F + */ + private EncryptionManager encryptionManager; + + /** + * Create a new license manager. + * + * @param publicKey + * the public key filename. + * @param privateKey + * the private key filename (null if not available). + * @throws GeneralSecurityException + * if the provided key are invalid. + * @throws IOException + * if the file doesn't exists + */ + public LicenseManager(String publicKey, String privateKey) throws GeneralSecurityException, IOException { + byte[] pubdata = EncryptionManager.readAll(new File(publicKey)); + byte[] privdata = null; + if (privateKey != null) { + privdata = EncryptionManager.readAll(new File(privateKey)); + } + this.encryptionManager = new EncryptionManager(pubdata, privdata); + } + + /** + * Create a new license manager. + * + * @param publicKey + * the public key file. + * @param privateKey + * the private key file (null if not available). + * @throws GeneralSecurityException + * if the provided key are invalid. + * @throws IOException + * if the file doesn't exists + */ + public LicenseManager(File publicKey, File privateKey) throws GeneralSecurityException, IOException { + byte[] pubdata = EncryptionManager.readAll(publicKey); + byte[] privdata = null; + if (privateKey != null) { + privdata = EncryptionManager.readAll(privateKey); + } + this.encryptionManager = new EncryptionManager(pubdata, privdata); + } + + /** + * Create a new license manager. + * + * @param publicKey + * an input stream containing the public key + * @param privateKey + * an input stream containing the private key + */ + public LicenseManager(InputStream publicKey, InputStream privateKey) throws GeneralSecurityException, IOException { + byte[] pubdata = EncryptionManager.readAll(publicKey); + byte[] privdata = null; + if (privateKey != null) { + privdata = EncryptionManager.readAll(privateKey); + } + this.encryptionManager = new EncryptionManager(pubdata, privdata); + } + + /** + * Create a new license manager. Generally, an application will not required + * more then one instance of license manager. + * + * @param publicKey + * the public key (can't be null). + * + * @param privateKey + * the private key (null if not available). + * @throws GeneralSecurityException + * if the provided key are invalid. + */ + public LicenseManager(byte[] publicKey, byte[] privateKey) throws GeneralSecurityException { + this.encryptionManager = new EncryptionManager(publicKey, privateKey); + } + + /** + * Read the content of an encrypted license file. + * + * @param file + * the location to the license file. + * @return the license object if the license file is valid, null otherwise. + * @throws IOException + * if file not found or read error. + * @throws SignatureException + * if this signature algorithm is unable to process the content + * of the file + * @throws NoSuchAlgorithmException + * if the SHA algorithm doesn't exists + * @throws InvalidKeyException + * if the public key is invalid + * @throws ClassNotFoundException + * if the implementation of {@link ILicense} stored in the file + * can't be found + */ + public ILicense readLicenseFile(File file) throws IOException, InvalidKeyException, NoSuchAlgorithmException, SignatureException, ClassNotFoundException { + + // Read the content of the file + byte[] sig; + byte[] data; + ObjectInputStream fileIn = new ObjectInputStream(new BufferedInputStream(new FileInputStream(file))); + try { + int sigLength = fileIn.readInt(); + sig = new byte[sigLength]; + fileIn.read(sig); + + ByteArrayOutputStream dataStream = new ByteArrayOutputStream(); + byte[] buf = new byte[SIZE]; + int len; + while ((len = fileIn.read(buf)) != -1) { + dataStream.write(buf, 0, len); + } + dataStream.flush(); + data = dataStream.toByteArray(); + dataStream.close(); + } finally { + fileIn.close(); + } + + // Validate the signature + if (!encryptionManager.verify(data, sig)) { + return null; + } + + // Read the license object from the data. + ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(data)); + try { + ILicense license = (ILicense) in.readObject(); + return license; + } finally { + in.close(); + } + + } + + /** + * Used to serialize a license object. + * + * @param license + * the license object. + * @param file + * the location where to save the new license file. If file + * exists, it's overwrite. + * @throws IOException + * if the file doesn't exists or can't be written to + * @throws SignatureException + * if this signature algorithm is unable to process the license + * data + * @throws NoSuchAlgorithmException + * if the algorithm SHA is not supported + * @throws InvalidKeyException + * if the private key is invalid. + */ + public void writeLicense(ILicense license, File file) throws IOException, InvalidKeyException, NoSuchAlgorithmException, SignatureException { + // Write the license information into a byte array. + ByteArrayOutputStream dataStream = new ByteArrayOutputStream(); + ObjectOutputStream out = new ObjectOutputStream(dataStream); + out.writeObject(license); + byte[] data = dataStream.toByteArray(); + out.close(); + + // Then sign the byte array + byte[] signature = this.encryptionManager.sign(data); + + // Write all the data into one single file. + ObjectOutputStream fileOut = new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream(file))); + try { + fileOut.writeInt(signature.length); + fileOut.write(signature); + fileOut.write(data); + fileOut.flush(); + } finally { + fileOut.close(); + } + + } + +} diff --git a/src/main/java/com/patrikdufresne/license/LicenseVersionExpiredException.java b/src/main/java/com/patrikdufresne/license/LicenseVersionExpiredException.java new file mode 100644 index 0000000000000000000000000000000000000000..9b95f0ddac2163cec2e1ae8e4fa0c72e52416023 --- /dev/null +++ b/src/main/java/com/patrikdufresne/license/LicenseVersionExpiredException.java @@ -0,0 +1,33 @@ +/** + * Copyright(C) 2013 Patrik Dufresne Service Logiciel + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.patrikdufresne.license; + +/** + * This exception is throw when the license version doesn't match the current + * version. + * + * @author Patrik Dufresne + * + */ +public class LicenseVersionExpiredException extends LicenseException { + + private static final long serialVersionUID = 8947235554238066208L; + + public LicenseVersionExpiredException() { + super("version expired"); + } + +} diff --git a/src/main/java/com/patrikdufresne/license/util/ILogger.java b/src/main/java/com/patrikdufresne/license/util/ILogger.java new file mode 100644 index 0000000000000000000000000000000000000000..a969500e2d8b4c2b0a09e7ae3b79a1c1dc322cb0 --- /dev/null +++ b/src/main/java/com/patrikdufresne/license/util/ILogger.java @@ -0,0 +1,66 @@ +/** + * Copyright(C) 2013 Patrik Dufresne Service Logiciel + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.patrikdufresne.license.util; + +/** + * A mechanism to log errors throughout the license framework. + *

+ * Clients may provide their own implementation to change how errors are logged + * from within the license framework. + *

+ * + */ +public interface ILogger { + /** + * Trace level (value: trace). + */ + public static final String TRACE = "trace"; + /** + * Debug level (value: debug). + */ + public static final String DEBUG = "debug"; + /** + * Info level (value: info). + */ + public static final String INFO = "info"; + /** + * Warn level (value: warn). + */ + public static final String WARN = "warn"; + /** + * Error level (value: error). + */ + public static final String ERROR = "error"; + + /** + * Logs the given status. + * + * @param level + * The level + * @param message + * The message to be logged. + */ + public void log(String level, String message); + + /** + * Logs the given exception. + * + * @param level + * @param exception + */ + public void log(String level, Throwable exception); + +} diff --git a/src/main/java/com/patrikdufresne/license/util/Policy.java b/src/main/java/com/patrikdufresne/license/util/Policy.java new file mode 100644 index 0000000000000000000000000000000000000000..d5c55be6d40920dcb542645dc6fa2cc1b51921a7 --- /dev/null +++ b/src/main/java/com/patrikdufresne/license/util/Policy.java @@ -0,0 +1,70 @@ +/** + * Copyright(C) 2013 Patrik Dufresne Service Logiciel + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.patrikdufresne.license.util; + +/** + * The Policy class handles settings for behavior, debug flags and logging + * within the license framework. + * + */ +public class Policy { + + private static ILogger log; + + /** + * Returns the dummy log to use if none has been set + */ + private static ILogger getDummyLog() { + return new ILogger() { + @Override + public void log(String level, String message) { + System.out.print(level + " " + message); + } + + @Override + public void log(String level, Throwable exception) { + exception.printStackTrace(System.out); + } + }; + } + + /** + * Returns the logger used by the license framework to log errors. + *

+ * The default logger prints the status to System.err. + *

+ * + * @return the logger + */ + public static ILogger getLog() { + if (log == null) { + log = getDummyLog(); + } + return log; + } + + /** + * Sets the logger used by the license framework to log errors. + * + * @param logger + * the logger to use, or null to use the default + * logger + */ + public static void setLog(ILogger logger) { + log = logger; + } + +} diff --git a/src/test/java/com/patrikdufresne/license/EncryptionManagerTest.java b/src/test/java/com/patrikdufresne/license/EncryptionManagerTest.java new file mode 100644 index 0000000000000000000000000000000000000000..033471643390dd9edec4797748b9fc68a653b725 --- /dev/null +++ b/src/test/java/com/patrikdufresne/license/EncryptionManagerTest.java @@ -0,0 +1,91 @@ +/** + * Copyright(C) 2013 Patrik Dufresne Service Logiciel + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.patrikdufresne.license; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; +import java.security.SignatureException; +import java.security.spec.InvalidKeySpecException; + +import org.junit.Before; +import org.junit.Test; + +import org.junit.Assert; + +/** + * Test the functionality provided by the class {@link EncryptionManager} + * + * @author Patrik Dufresne + * + */ +public class EncryptionManagerTest { + + private EncryptionManager manager; + + private byte[] data; + + @Before + public void initEncryptionManager() throws IOException, NoSuchAlgorithmException, InvalidKeySpecException { + + byte[] pubKey = EncryptionManager.readAll(getClass().getResourceAsStream("/pubkey.der")); + byte[] privateKey = EncryptionManager.readAll(getClass().getResourceAsStream("/privkey.der")); + this.manager = new EncryptionManager(pubKey, privateKey); + + // Prepare data + String string = "This is some data to by sign"; + this.data = string.getBytes(); + } + + @Test + public void sign_WithData_ReturnSignature() throws InvalidKeyException, NoSuchAlgorithmException, SignatureException { + + byte[] sig = this.manager.sign(data); + + } + + @Test + public void verify_WithDataAndGoodSignature_ReturnTrue() + throws InvalidKeyException, + NoSuchAlgorithmException, + SignatureException, + FileNotFoundException, + IOException { + + byte[] sig = this.manager.sign(data); + + Assert.assertTrue(this.manager.verify(data, sig)); + + } + + @Test + public void verify_WithDataAndWrongSignature_ReturnTrue() + throws InvalidKeyException, + NoSuchAlgorithmException, + SignatureException, + FileNotFoundException, + IOException { + + byte[] sig = this.manager.sign(data); + sig[0] = (byte) (((int) sig[0]) + 3); + + Assert.assertFalse(this.manager.verify(data, sig)); + + } + +} diff --git a/src/test/java/com/patrikdufresne/license/KeyManagerTest.java b/src/test/java/com/patrikdufresne/license/KeyManagerTest.java new file mode 100644 index 0000000000000000000000000000000000000000..d5461775de612b470ad3aac6cf4d6c5dfcb479da --- /dev/null +++ b/src/test/java/com/patrikdufresne/license/KeyManagerTest.java @@ -0,0 +1,57 @@ +/** + * Copyright(C) 2013 Patrik Dufresne Service Logiciel + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.patrikdufresne.license; + +import org.junit.Before; +import org.junit.Test; + +public class KeyManagerTest { + + private KeyManager manager; + + @Before + public void initKeyManager() { + this.manager = new KeyManager(); + } + + @Test + public void generateKey_WithAuthCode_ReturnKey() { + + String key = this.manager.generateKey(3, "coucou"); + + } + + @Test + public void validateKey_WithValidKey_ReturnTrue() throws KeyInvalidException, KeyBlackListedException { + + String key = this.manager.generateKey(3, "coucou"); + + this.manager.validateKey(key); + + } + + @Test(expected = KeyInvalidException.class) + public void validateKey_WithInvalidKey_ReturnTrue() throws KeyInvalidException, KeyBlackListedException { + + String key = this.manager.generateKey(3, "coucou"); + + key = key.replace("0", "1"); + + this.manager.validateKey(key); + + } + +} diff --git a/src/test/java/com/patrikdufresne/license/LicenseManagerTest.java b/src/test/java/com/patrikdufresne/license/LicenseManagerTest.java new file mode 100644 index 0000000000000000000000000000000000000000..96f6100ca58fb0f41c8024ad29d6b7cc9c1c72b9 --- /dev/null +++ b/src/test/java/com/patrikdufresne/license/LicenseManagerTest.java @@ -0,0 +1,95 @@ +/** + * Copyright(C) 2013 Patrik Dufresne Service Logiciel + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.patrikdufresne.license; + +import static org.junit.Assert.*; + +import java.io.File; +import java.io.IOException; +import java.security.GeneralSecurityException; +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; +import java.security.SignatureException; + +import org.junit.Before; +import org.junit.Test; + +/** + * This class test all the functionnality provided by the {@link LicenseManager} + * . + * + * @author ikus060 + * + */ +public class LicenseManagerTest { + + static class MockLicense extends AbstractLicense { + + private static final long serialVersionUID = -4612807836761969030L; + + } + + private LicenseManager manager; + + @Before + public void initLicenseManager() throws GeneralSecurityException, IOException { + this.manager = new LicenseManager(getClass().getResourceAsStream("/pubkey.der"), getClass().getResourceAsStream("/privkey.der")); + } + + /** + * Check to create a license file + * + * @throws IOException + * @throws SignatureException + * @throws NoSuchAlgorithmException + * @throws InvalidKeyException + */ + @Test + public void writeLicense_WithLicense_CreateTheFile() throws InvalidKeyException, NoSuchAlgorithmException, SignatureException, IOException { + MockLicense license = new MockLicense(); + File file = new File("unittest.lic"); + manager.writeLicense(license, file); + assertTrue(file.exists()); + } + + /** + * Read the license file. + * + * @throws IOException + * @throws SignatureException + * @throws NoSuchAlgorithmException + * @throws InvalidKeyException + * @throws ClassNotFoundException + */ + @Test + public void readLicense_WithValidFile_ReadLicense() + throws InvalidKeyException, + NoSuchAlgorithmException, + SignatureException, + IOException, + ClassNotFoundException { + MockLicense license = new MockLicense(); + File file = new File("unittest2.lic"); + manager.writeLicense(license, file); + assertTrue(file.exists()); + + // Read the file + MockLicense license2 = (MockLicense) manager.readLicenseFile(file); + assertNotNull(license2); + + } + +} diff --git a/unitest/privkey.der b/src/test/resources/privkey.der similarity index 100% rename from unitest/privkey.der rename to src/test/resources/privkey.der diff --git a/unitest/privkey.pem b/src/test/resources/privkey.pem similarity index 100% rename from unitest/privkey.pem rename to src/test/resources/privkey.pem diff --git a/unitest/pubkey.der b/src/test/resources/pubkey.der similarity index 100% rename from unitest/pubkey.der rename to src/test/resources/pubkey.der diff --git a/unitest/.classpath b/unitest/.classpath deleted file mode 100644 index c8824494044dbb65ef5130a1db7ff5621b4c13b8..0000000000000000000000000000000000000000 --- a/unitest/.classpath +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/unitest/.gitignore b/unitest/.gitignore deleted file mode 100644 index 5e56e040ec0902e58df8573adaec65c5da6e9304..0000000000000000000000000000000000000000 --- a/unitest/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/bin diff --git a/unitest/.project b/unitest/.project deleted file mode 100644 index a8756e7e7bc4aa520c996b64c41c7fd7b87c82c2..0000000000000000000000000000000000000000 --- a/unitest/.project +++ /dev/null @@ -1,17 +0,0 @@ - - - license-unittest - - - - - - org.eclipse.jdt.core.javabuilder - - - - - - org.eclipse.jdt.core.javanature - - diff --git a/unitest/.settings/org.eclipse.jdt.core.prefs b/unitest/.settings/org.eclipse.jdt.core.prefs deleted file mode 100644 index e4d9131187a607427f6e26858e30e1c3b3d49e8f..0000000000000000000000000000000000000000 --- a/unitest/.settings/org.eclipse.jdt.core.prefs +++ /dev/null @@ -1,12 +0,0 @@ -#Tue Apr 03 19:11:01 EDT 2012 -eclipse.preferences.version=1 -org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 -org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve -org.eclipse.jdt.core.compiler.compliance=1.6 -org.eclipse.jdt.core.compiler.debug.lineNumber=generate -org.eclipse.jdt.core.compiler.debug.localVariable=generate -org.eclipse.jdt.core.compiler.debug.sourceFile=generate -org.eclipse.jdt.core.compiler.problem.assertIdentifier=error -org.eclipse.jdt.core.compiler.problem.enumIdentifier=error -org.eclipse.jdt.core.compiler.source=1.6 diff --git a/unitest/src/com/patrikdufresne/license/EncryptionManagerTest.java b/unitest/src/com/patrikdufresne/license/EncryptionManagerTest.java deleted file mode 100644 index 74daf5a2e5341b16b72e97a3dfdf4f2156260357..0000000000000000000000000000000000000000 --- a/unitest/src/com/patrikdufresne/license/EncryptionManagerTest.java +++ /dev/null @@ -1,72 +0,0 @@ -package com.patrikdufresne.license; - -import java.io.File; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.security.InvalidKeyException; -import java.security.NoSuchAlgorithmException; -import java.security.SignatureException; -import java.security.spec.InvalidKeySpecException; - -import org.junit.Before; -import org.junit.Test; - -import org.junit.Assert; - -/** - * Test the functionality provided by the class {@link EncryptionManager} - * - * @author Patrik Dufresne - * - */ -public class EncryptionManagerTest { - - private EncryptionManager manager; - - private byte[] data; - - @Before - public void initEncryptionManager() throws IOException, - NoSuchAlgorithmException, InvalidKeySpecException { - - byte[] pubKey = EncryptionManager.readAll(new File("pubkey.der")); - byte[] privateKey = EncryptionManager.readAll(new File("privkey.der")); - this.manager = new EncryptionManager(pubKey, privateKey); - - // Prepare data - String string = "This is some data to by sign"; - this.data = string.getBytes(); - } - - @Test - public void sign_WithData_ReturnSignature() throws InvalidKeyException, - NoSuchAlgorithmException, SignatureException { - - byte[] sig = this.manager.sign(data); - - } - - @Test - public void verify_WithDataAndGoodSignature_ReturnTrue() - throws InvalidKeyException, NoSuchAlgorithmException, - SignatureException, FileNotFoundException, IOException { - - byte[] sig = this.manager.sign(data); - - Assert.assertTrue(this.manager.verify(data, sig)); - - } - - @Test - public void verify_WithDataAndWrongSignature_ReturnTrue() - throws InvalidKeyException, NoSuchAlgorithmException, - SignatureException, FileNotFoundException, IOException { - - byte[] sig = this.manager.sign(data); - sig[0] = (byte) (((int) sig[0]) + 3); - - Assert.assertFalse(this.manager.verify(data, sig)); - - } - -} diff --git a/unitest/src/com/patrikdufresne/license/KeyManagerTest.java b/unitest/src/com/patrikdufresne/license/KeyManagerTest.java deleted file mode 100644 index 5ffe968fe7a3579546e63a7a6d7853dd2ec0c297..0000000000000000000000000000000000000000 --- a/unitest/src/com/patrikdufresne/license/KeyManagerTest.java +++ /dev/null @@ -1,44 +0,0 @@ -package com.patrikdufresne.license; - -import org.junit.Before; -import org.junit.Test; - -public class KeyManagerTest { - - private KeyManager manager; - - @Before - public void initKeyManager() { - this.manager = new KeyManager(); - } - - @Test - public void generateKey_WithAuthCode_ReturnKey() { - - String key = this.manager.generateKey(3, "coucou"); - - } - - @Test - public void validateKey_WithValidKey_ReturnTrue() - throws KeyInvalidException, KeyBlackListedException { - - String key = this.manager.generateKey(3, "coucou"); - - this.manager.validateKey(key); - - } - - @Test(expected = KeyInvalidException.class) - public void validateKey_WithInvalidKey_ReturnTrue() - throws KeyInvalidException, KeyBlackListedException { - - String key = this.manager.generateKey(3, "coucou"); - - key = key.replace("0", "1"); - - this.manager.validateKey(key); - - } - -} diff --git a/unitest/src/com/patrikdufresne/license/LicenseManagerTest.java b/unitest/src/com/patrikdufresne/license/LicenseManagerTest.java deleted file mode 100644 index aa853a600a81f9ebb80f07363ceb4c15aa582873..0000000000000000000000000000000000000000 --- a/unitest/src/com/patrikdufresne/license/LicenseManagerTest.java +++ /dev/null @@ -1,80 +0,0 @@ -package com.patrikdufresne.license; - -import static org.junit.Assert.*; - -import java.io.File; -import java.io.IOException; -import java.security.GeneralSecurityException; -import java.security.InvalidKeyException; -import java.security.NoSuchAlgorithmException; -import java.security.SignatureException; - -import org.junit.Before; -import org.junit.Test; - -/** - * This class test all the functionnality provided by the {@link LicenseManager} - * . - * - * @author ikus060 - * - */ -public class LicenseManagerTest { - - static class MockLicense extends AbstractLicense { - - private static final long serialVersionUID = -4612807836761969030L; - - } - - private LicenseManager manager; - - @Before - public void initLicenseManager() throws GeneralSecurityException, - IOException { - this.manager = new LicenseManager("pubkey.der", "privkey.der"); - } - - /** - * Check to create a license file - * - * @throws IOException - * @throws SignatureException - * @throws NoSuchAlgorithmException - * @throws InvalidKeyException - */ - @Test - public void writeLicense_WithLicense_CreateTheFile() - throws InvalidKeyException, NoSuchAlgorithmException, - SignatureException, IOException { - MockLicense license = new MockLicense(); - File file = new File("unittest.lic"); - manager.writeLicense(license, file); - assertTrue(file.exists()); - } - - /** - * Read the license file. - * - * @throws IOException - * @throws SignatureException - * @throws NoSuchAlgorithmException - * @throws InvalidKeyException - * @throws ClassNotFoundException - */ - @Test - public void readLicense_WithValidFile_ReadLicense() - throws InvalidKeyException, NoSuchAlgorithmException, - SignatureException, IOException, ClassNotFoundException { - MockLicense license = new MockLicense(); - File file = new File("unittest2.lic"); - manager.writeLicense(license, file); - assertTrue(file.exists()); - - // Read the file - MockLicense license2 = (MockLicense) manager.readLicenseFile(file); - assertNotNull(license2); - - } - -}