diff --git a/src/main/java/com/patrikdufresne/license/EncryptionManager.java b/src/main/java/com/patrikdufresne/license/EncryptionManager.java deleted file mode 100644 index d7bb7960b70ab975b06656254af1d6d567175da4..0000000000000000000000000000000000000000 --- a/src/main/java/com/patrikdufresne/license/EncryptionManager.java +++ /dev/null @@ -1,179 +0,0 @@ -/** - * Copyright(C) 2018 Patrik Dufresne Service Logiciel inc - * - * 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 BUF_SIZE = 4096; - - 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(BUF_SIZE); - byte[] buf = new byte[BUF_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/KeyBlackListedException.java b/src/main/java/com/patrikdufresne/license/KeyBlackListedException.java deleted file mode 100644 index 7bf65fd923ce113a6b7e909844c8e68363eca498..0000000000000000000000000000000000000000 --- a/src/main/java/com/patrikdufresne/license/KeyBlackListedException.java +++ /dev/null @@ -1,32 +0,0 @@ -/** - * Copyright(C) 2018 Patrik Dufresne Service Logiciel inc - * - * 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 deleted file mode 100644 index e7724df9640b6c7040f5744530425895eb0dbdb8..0000000000000000000000000000000000000000 --- a/src/main/java/com/patrikdufresne/license/KeyInvalidException.java +++ /dev/null @@ -1,32 +0,0 @@ -/** - * Copyright(C) 2018 Patrik Dufresne Service Logiciel inc - * - * 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 deleted file mode 100644 index aa4acee96867ea2215a008e36d51bf55927a1922..0000000000000000000000000000000000000000 --- a/src/main/java/com/patrikdufresne/license/KeyManager.java +++ /dev/null @@ -1,356 +0,0 @@ -/** - * Copyright(C) 2018 Patrik Dufresne Service Logiciel inc - * - * 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)); - } - 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/LicenseManager.java b/src/main/java/com/patrikdufresne/license/LicenseManager.java index 1a8435ae298c851216097a20d94ae58e7a0a9889..4d7582a4d6d354e22aca75edf651780b93b7270e 100644 --- a/src/main/java/com/patrikdufresne/license/LicenseManager.java +++ b/src/main/java/com/patrikdufresne/license/LicenseManager.java @@ -17,15 +17,24 @@ package com.patrikdufresne.license; import java.io.ByteArrayOutputStream; import java.io.File; -import java.io.FileReader; -import java.io.FileWriter; +import java.io.FileInputStream; +import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; +import java.io.InputStreamReader; import java.io.ObjectOutputStream; +import java.io.OutputStreamWriter; import java.security.GeneralSecurityException; 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.PKCS8EncodedKeySpec; +import java.security.spec.X509EncodedKeySpec; import java.util.ArrayList; import java.util.Collections; import java.util.Date; @@ -48,10 +57,126 @@ public class LicenseManager { * Property to store the signature. */ private static final String SIGNATURE = "signature"; + + /** + * Define the encoding to be used to read and write the license file. Since the license may be generate on different + * platform with different default encoding, we need to hardcode this into a fixed encoding. UTF-8 should be a good + * choice. + */ + private static final String ENCODING = "UTF-8"; + + private static final int BUF_SIZE = 4096; + + private PublicKey publicKey; + + /** + * Our private key. + */ + private PrivateKey privateKey; + + /** + * This function is used to read a stream. + * + * @param input + * the input stream + * @return the data read from the stream + * @throws IOException + */ + private static byte[] readAll(InputStream input) throws IOException { + if (input == null) { + return null; + } + // Read the content of the file and store it in a byte array. + ByteArrayOutputStream out = new ByteArrayOutputStream(BUF_SIZE); + byte[] buf = new byte[BUF_SIZE]; + int size; + while ((size = input.read(buf)) != -1) { + out.write(buf, 0, size); + } + return out.toByteArray(); + } + /** - * The encryption manager used by this class.F + * 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 */ - private EncryptionManager encryptionManager; + private static byte[] readAll(File file) throws IOException { + if (file == null) { + return null; + } + 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 + */ + protected 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. + */ + protected 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(); + + } /** * Utility function to easily validate a license file. @@ -99,7 +224,21 @@ public class LicenseManager { * if the provided key are invalid. */ public LicenseManager(byte[] publicKey, byte[] privateKey) throws GeneralSecurityException { - this.encryptionManager = new EncryptionManager(publicKey, privateKey); + + 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); + } + } /** @@ -115,12 +254,7 @@ public class LicenseManager { * 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); + this(readAll(publicKey), readAll(privateKey)); } /** @@ -132,12 +266,7 @@ public class LicenseManager { * 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); + this(readAll(publicKey), readAll(privateKey)); } /** @@ -187,7 +316,7 @@ public class LicenseManager { String base64Signature = null; // Read the license file as a property file. Properties prop = new Properties(); - prop.load(new FileReader(file)); + prop.load(new InputStreamReader(new FileInputStream(file), ENCODING)); License lic = new License(); for (Object key : prop.keySet()) { String value = (String) prop.get(key); @@ -207,7 +336,7 @@ public class LicenseManager { byte[] data = writeLicenseToByteArray(lic); // Validate the signature - if (!encryptionManager.verify(data, sig)) { + if (!verify(data, sig)) { throw new LicenseException("invalid license signature"); } @@ -238,7 +367,7 @@ public class LicenseManager { byte[] data = writeLicenseToByteArray(lic); // Then sign the byte array - byte[] signature = this.encryptionManager.sign(data); + byte[] signature = sign(data); String base64signature = Base64.encode(signature); // Create property file @@ -249,7 +378,7 @@ public class LicenseManager { prop.put(SIGNATURE, base64signature); // Write the property file - prop.store(new FileWriter(file), "License file"); + prop.store(new OutputStreamWriter(new FileOutputStream(file), ENCODING), "License file"); } /** diff --git a/src/test/java/com/patrikdufresne/license/AllTests.java b/src/test/java/com/patrikdufresne/license/AllTests.java deleted file mode 100644 index 9a8ab6f4a402b50d217d3ec0690c9c4ec4bc9bc4..0000000000000000000000000000000000000000 --- a/src/test/java/com/patrikdufresne/license/AllTests.java +++ /dev/null @@ -1,25 +0,0 @@ -/** - * Copyright(C) 2018 Patrik Dufresne Service Logiciel inc - * - * 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.runner.RunWith; -import org.junit.runners.Suite; - -@RunWith(Suite.class) -@Suite.SuiteClasses( { EncryptionManagerTest.class, KeyManagerTest.class, LicenseManagerTest.class }) -public class AllTests { - -} diff --git a/src/test/java/com/patrikdufresne/license/EncryptionManagerTest.java b/src/test/java/com/patrikdufresne/license/EncryptionManagerTest.java deleted file mode 100644 index 1c33abe86cde42f0fdbb22f57f08d76674abc6a4..0000000000000000000000000000000000000000 --- a/src/test/java/com/patrikdufresne/license/EncryptionManagerTest.java +++ /dev/null @@ -1,91 +0,0 @@ -/** - * Copyright(C) 2018 Patrik Dufresne Service Logiciel inc - * - * 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 deleted file mode 100644 index 92d05760bc8451e0c098ca04a8e03398dda35345..0000000000000000000000000000000000000000 --- a/src/test/java/com/patrikdufresne/license/KeyManagerTest.java +++ /dev/null @@ -1,57 +0,0 @@ -/** - * Copyright(C) 2018 Patrik Dufresne Service Logiciel inc - * - * 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); - - } - -}