com.POLIS.licensing.common.license.AbstractSerializationBasedLicense.java Source code

Java tutorial

Introduction

Here is the source code for com.POLIS.licensing.common.license.AbstractSerializationBasedLicense.java

Source

/*
 * 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.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectOutput;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.KeyFactory;
import java.security.KeyPairGenerator;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.Security;
import java.security.Signature;
import java.security.SignatureException;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
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.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import org.apache.commons.codec.binary.Base64;
import org.bouncycastle.jce.provider.BouncyCastleProvider;

/**
 *
 * @author Martin
 */
public abstract class AbstractSerializationBasedLicense implements License, Serializable {

    public static final String signatureEncoding = "SHA512withRSA";
    public static final String symmetricEncoding = "AES/ECB/withCTS";
    public static final String symmetricKeyType = "AES";
    public static final String asymmetricEncoding = "RSA/NONE/PKCS1Padding";
    public static final String provider = "BC";

    private byte[] signature;

    protected abstract String getFieldsAsString();

    public AbstractSerializationBasedLicense() {

    }

    @Override
    public void signLicense(PrivateKey privateSignatureKey)
            throws BadLicenseException, SystemStateException, OperationException {
        try {
            Signature instance = Signature.getInstance(signatureEncoding, provider);
            instance.initSign(privateSignatureKey);
            instance.update(getFieldsAsString().getBytes());
            signature = instance.sign();
        } catch (NoSuchAlgorithmException | NoSuchProviderException ex) {
            throw new SystemStateException("Could not sign the license. Algorithm not found", ex);
        } catch (InvalidKeyException | SignatureException ex) {
            throw new OperationException("Could not sign the license.", ex);
        }
    }

    @Override
    public boolean verifyLicense(PublicKey senderSignatureKey)
            throws BadLicenseException, SystemStateException, OperationException {

        if (signature == null) {
            throw new OperationException("Could not vertify signature. License was never signed");
        }
        try {
            Signature instance = Signature.getInstance(signatureEncoding, provider);
            instance.initVerify(senderSignatureKey);
            instance.update(getFieldsAsString().getBytes());
            return instance.verify(signature);
        } catch (NoSuchAlgorithmException | NoSuchProviderException ex) {
            throw new SystemStateException("Could not verify the license. Algorithm not found", ex);
        } catch (InvalidKeyException | SignatureException ex) {
            throw new OperationException("Could not verify the license.", ex);
        }
    }

    @Override
    public String getEncryptedLicense(PublicKey targetKey) throws SystemStateException, OperationException {
        byte[] licenseAsBytes;
        try (ByteArrayOutputStream bos = new ByteArrayOutputStream();
                ObjectOutput out = new ObjectOutputStream(bos)) {
            out.writeObject(this);
            licenseAsBytes = bos.toByteArray();
        } catch (IOException ex) {
            throw new OperationException("An error occured while serializing the license", ex);
        }
        SecureRandom random = new SecureRandom();
        Cipher aescipher;
        Cipher rsacipher;

        KeyGenerator aesgenerator;
        Key symkey;
        try {
            aesgenerator = KeyGenerator.getInstance(symmetricKeyType, provider);
            aesgenerator.init(128, random);
            symkey = aesgenerator.generateKey();
        } catch (NoSuchAlgorithmException | NoSuchProviderException ex) {
            throw new SystemStateException("The specified symkey could not be generated.", ex);
        }

        try {
            aescipher = Cipher.getInstance(symmetricEncoding, provider);
            rsacipher = Cipher.getInstance(asymmetricEncoding, provider);

            aescipher.init(Cipher.ENCRYPT_MODE, symkey);
            rsacipher.init(Cipher.ENCRYPT_MODE, targetKey);
        } catch (NoSuchAlgorithmException | NoSuchProviderException
                | /*InvalidKeySpecException |*/ NoSuchPaddingException | InvalidKeyException ex) {
            throw new SystemStateException("The specified encryption provider or algorithm was not found", ex);
        }

        String encryptedLicense;
        try {
            byte[] encryptedsymkey = rsacipher.doFinal(symkey.getEncoded());

            byte[] encryptedlicense = aescipher.doFinal(licenseAsBytes);
            byte[] licenseWithKey = new byte[encryptedsymkey.length + encryptedlicense.length];
            System.arraycopy(encryptedsymkey, 0, licenseWithKey, 0, encryptedsymkey.length);
            System.arraycopy(encryptedlicense, 0, licenseWithKey, encryptedsymkey.length, encryptedlicense.length);
            encryptedLicense = Base64.encodeBase64String(licenseWithKey);
        } catch (IllegalBlockSizeException | BadPaddingException ex) {
            throw new OperationException("Could not encode to base64", ex);
        }
        return encryptedLicense;

    }

    protected byte[] getSignature() {
        return signature;
    }

}