Java tutorial
/* * To change this license header, choose License Headers in Project Properties. * To change this template file, choose Tools | Templates * and open the template in the editor. */ package com.POLIS.licensing.common.license; import com.POLIS.licensing.common.exception.BadLicenseException; import com.POLIS.licensing.common.exception.OperationException; import com.POLIS.licensing.common.exception.SystemStateException; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.ObjectInput; import java.io.ObjectInputStream; import java.security.InvalidKeyException; import java.security.Key; import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; import java.security.PrivateKey; import java.security.PublicKey; import java.util.logging.Level; import java.util.logging.Logger; import javax.crypto.BadPaddingException; import javax.crypto.Cipher; import javax.crypto.IllegalBlockSizeException; import javax.crypto.NoSuchPaddingException; import javax.crypto.spec.SecretKeySpec; import org.apache.commons.codec.binary.Base64; /** * * @author Martin */ public abstract class AbstractSerializationBasedLicenseFactory<T extends AbstractSerializationBasedLicense> implements LicenseFactory<T> { private static int symkeySize = 128; @Override public T loadLicense(String data, PrivateKey senderEncryptionKey, PublicKey senderSignatureKey) throws BadLicenseException, SystemStateException, OperationException { byte[] decodedLicense; decodedLicense = Base64.decodeBase64(data); byte[] encryptedSymKey = new byte[symkeySize]; byte[] encryptedLicense = new byte[decodedLicense.length - symkeySize]; byte[] decryptedSymKey; byte[] decryptedLicense; Key symkey; System.arraycopy(decodedLicense, 0, encryptedSymKey, 0, symkeySize); System.arraycopy(decodedLicense, symkeySize, encryptedLicense, 0, decodedLicense.length - symkeySize); Cipher asymetriccipher; try { asymetriccipher = Cipher.getInstance(AbstractSerializationBasedLicense.asymmetricEncoding, AbstractSerializationBasedLicense.provider); asymetriccipher.init(Cipher.DECRYPT_MODE, senderEncryptionKey); } catch (NoSuchAlgorithmException | NoSuchProviderException | /*InvalidKeySpecException |*/ NoSuchPaddingException | InvalidKeyException ex) { throw new SystemStateException("The specified encryption provider or algorithm was not found", ex); } try { decryptedSymKey = asymetriccipher.doFinal(encryptedSymKey); symkey = new SecretKeySpec(decryptedSymKey, "AES"); } catch (IllegalBlockSizeException | BadPaddingException ex) { throw new SystemStateException("Could not decode the symkey for the license", ex); } Cipher symmetriccipher; try { symmetriccipher = Cipher.getInstance(AbstractSerializationBasedLicense.symmetricEncoding, AbstractSerializationBasedLicense.provider); symmetriccipher.init(Cipher.DECRYPT_MODE, symkey); } catch (NoSuchAlgorithmException | NoSuchProviderException | /*InvalidKeySpecException |*/ NoSuchPaddingException | InvalidKeyException ex) { throw new SystemStateException("The specified encryption provider or algorithm was not found", ex); } try { decryptedLicense = symmetriccipher.doFinal(encryptedLicense); } catch (IllegalBlockSizeException | BadPaddingException ex) { throw new SystemStateException("Could not encode to base64", ex); } T license; try { license = getDeserializedObject(decryptedLicense); } catch (IOException | ClassNotFoundException ex) { throw new SystemStateException("An error occurred while reading the license from the input byte array.", ex); } if (license.verifyLicense(senderSignatureKey)) { return license; } else throw new BadLicenseException(license, "The license could not be verified with the specified signature decryption key"); } protected abstract T getDeserializedObject(byte[] objectAsBytes) throws IOException, ClassNotFoundException, SystemStateException; protected AbstractSerializationBasedLicense defaultGetDeserializedObject(byte[] objectAsBytes) throws IOException, ClassNotFoundException, SystemStateException { AbstractSerializationBasedLicense license; try (ByteArrayInputStream bis = new ByteArrayInputStream(objectAsBytes); ObjectInput in = new ObjectInputStream(bis)) { Object likelyLicense = in.readObject(); try { license = (AbstractSerializationBasedLicense) likelyLicense; } catch (ClassCastException ex) { throw new SystemStateException("Could not cast " + likelyLicense.getClass().getCanonicalName() + ", expected a subclass of " + AbstractSerializationBasedLicense.class.getCanonicalName(), ex); } } return license; } }