Class License


  • public class License
    extends Object
    A license describes the rights a certain user has. The rights are represented by Features. Each feature has a name, type and a value. The license is essentially the set of features.

    As examples features can be license expiration date and time, number of users allowed to use the software, name of rights and so on.

    • Constructor Detail

      • License

        public License()
      • License

        protected License​(License license)
    • Method Detail

      • get

        public Feature get​(String name)
        Get a feature of a given name from the license or null if there is no feature for the name in the license.
        Parameters:
        name - the name of the feature we want to retrieve
        Returns:
        the feature object.
      • isExpired

        public boolean isExpired()
        Checks the expiration date of the license and returns true if the license has expired.

        The expiration date is stored in the license feature expiryDate. A license is expired if the current date is after the specified expiryDate. At the given date (ms precision) the license is still valid.

        The method does not check that the license is properly signed or not. That has to be checked using a separate call to the underlying license.

        Returns:
        true if the license has expired.
      • setExpiry

        public void setExpiry​(Date expiryDate)
        Set the expiration date of the license.
        Parameters:
        expiryDate - the date when the license expires
      • sign

        public void sign​(PrivateKey key,
                         String digest)
                  throws NoSuchAlgorithmException,
                         NoSuchPaddingException,
                         InvalidKeyException,
                         BadPaddingException,
                         IllegalBlockSizeException
        Sign the license.

        The license is signed the following way:

        1. Add the digest algorithm string to the license as a feature. The feature name is signatureDigest (name is defined in the constant DIGEST_KEY in this class).
        2. The license is converted to binary format
        3. A digest is created from the binary license using the message digest algorithm named by the digest parameter
        4. The digest is encrypted using the key (which also has the information about the algorithm).
        5. The encrypted digest is added to the license as a new BINARY feature as signature.
        Parameters:
        key - the private key to be used to create the signature
        digest - the name of the digest algorithm
        Throws:
        NoSuchAlgorithmException - this exception comes from the underlying encryption library
        NoSuchPaddingException - this exception comes from the underlying encryption library
        InvalidKeyException - this exception comes from the underlying encryption library
        BadPaddingException - this exception comes from the underlying encryption library
        IllegalBlockSizeException - this exception comes from the underlying encryption library
      • isOK

        public boolean isOK​(byte[] key)
        Parameters:
        key - serialized encryption key to check the authenticity of the license signature
        Returns:
        see isOK(PublicKey)
      • isOK

        public boolean isOK​(PublicKey key)
        Returns true if the license is signed, and the authenticity of the signature can be checked successfully using the key.
        Parameters:
        key - encryption key to check the authenticity of the license signature
        Returns:
        true if the license was properly signed and is intact. In any other cases it returns false.
      • add

        public Feature add​(Feature feature)
        Add a feature to the license. Note that adding a feature to a license renders the license signature invalid. Adding the feature does not remove the signature feature though if there was any added previously. You can calculate the signature of the license and add it to the license after you have added all features. Adding the signature to the license as a feature does not ruin the signature because the signature is eventually ignored when calculating the signature. The signature has to be a BINARY feature.

        The method throws exception in case the feature is the license signature, and the type is not BINARY.

        Parameters:
        feature - is added to the license
        Returns:
        the previous feature of the same name but presumably different type and value or null in case there was no previous feature in the license of the same name.
      • toString

        public String toString()
        Converts a license to string. The string contains all the features in a guaranteed order. The actual ordering is not defined, the only thing guaranteed is that the features are listed in the same order whenever toString is invoked.

        Every feature is formatted as

             name:TYPE=value
         

        when the value is multiline then it is converted to be multiline. Multiline strings are represented as usually in unix, with the HERE_STRING. The value in this case starts right after the = character with the << characters, and a spacial start/stop string to the end of the line that does not appear as a single line inside the multiline value. This value signals the end of the string and all other lines before it is part of the multiline string. For example:

        
                   feature name : STRING =<<END
                     this is
                       a multi-line
                         string
                   END
         

        In this example the string END signals the end of the string, and the lines between are part of the multi-line string. A feature string is also converted to multi-line representation if it happens to start with the characters <<.

        The returned string can be saved, transferred by eMail or other textual channel and finally it can be used as argument to License.Create.from(String).

        Overrides:
        toString in class Object
        Returns:
        the converted license as a string.
      • getFeatures

        public Map<String,​Feature> getFeatures()

        Returns the features of the license in a map. The keys of the map are the names of the features. The values are the feature objects (which also contain the name).

        Note that the invocation of this method has its cost as it recreates the returned map every time. It does not keep track if the set of features has changed since the last time the method was called.

        Returns:
        the collected map
      • setLicenseId

        public UUID setLicenseId()
        Generates a new license identifier.

        This identifier is also stored in the license as a feature with the name licenseId, thus there is no need to create an extra feature and add it to the license. (The type of the feature is obviously UUID.)

        Generating UUID can be handy when you want to identify each license individually. For example, you want to store revocation information about each license. The url to check the revocation may contain the ${licenseId} place holder that will be replaced by the actual uuid stored in the license.

        Returns:
        the generated identifier.
      • getLicenseId

        public UUID getLicenseId()
        Get the license identifier. The identifier of the license is a random UUID (128 bit random value) that can optionally be set and can be used to identify the license. This ID can be used as a reference to the license in databases, URLs.
        An example use it is to upload a simple, presumably zero length file to a publicly reachable server with the name of the license UUID so that it can be retrieved via a URL containing the UUID. The licensed program tries to download the file and in case the response code is 200 OK then it assumes that the license is OK. If the server is not reachable or for some other reason it cannot reach the file it may assume that this is a technical glitch and go on working for a while. However, if the response is a definitive 404 it means that the file was removed: the license is revoked.
        Returns:
        the UUID format identifier of the license or null in case the license does not contain an ID.
      • fingerprint

        public UUID fingerprint()
        Get the fingerprint of a license. The fingerprint is a 128bit value calculated from the license itself using the MD5 algorithm. The fingerprint is represented as a UUID. The fingerprint is never stored in the license as a feature. If the fingerprint is stored in the license as a feature then the fingerprint of the license changes so the stored fingerprint will not be the fingerprint of the license any more.

        The calculation of the fingerprint ignores the signature of the license as well as the feature that stores the name of the signature digest algorithm (usually "SHA-512"). This is to ensure that even if you change the signature on the license using a different digest algorithm: fingerprint will not change. The fingerprint is relevant to the core content of the license.

        Since the fingerprint is calculated from the binary representation of the license using the MD5 algorithm it is likely that each license will have different fingerprint. This fingerprint can be used to identify licenses similarly like the license id (see setLicenseId(UUID),getLicenseId()). The fingerprint can be used even when the license does not have random ID stored in the license.


        NOTE:

        This fingerprint calculation is not used when the license is signed. MD5 as a message digest is not considered to be safe enough for electronic signature. License signature uses a message digest the caller specifies and which is implemented in Java. Usually SHA-512. It can actually be MD5 if the caller specifies "MD5" as the digest algorithm, but it is not recommended and even in that case this fingerprint calculation has nothing to do with the license signature process.


        Returns:
        the calculated fingerprint of the license.
      • setLicenseId

        public void setLicenseId​(UUID licenseId)
        Set the UUID of a license. Note that this UUID can be generated calling the method setLicenseId() without any argument, which method automatically calls this method setting the generated UUID to be the identifier of the license.
        Parameters:
        licenseId - the uuid that was generated somewhere.
      • serialized

        public byte[] serialized()
        Get the license serialized (not standard Java serialized!!!) as a byte array. This method is used to save the license in BINARY format but not to sign the license. The returned byte array contains all the features including the signature of the license.
        Returns:
        the license in binary format as a byte array
      • unsigned

        public byte[] unsigned()
        Get the license as a byte[] without the signature key. This byte array is used to create the signature of the license. Obviously, the signature itself cannot be part of the signed part of the license.

        This method can be used when the license is going to be signed as well as when the signature is verified (though there are direct methods to sign and verify a license for upper layers). When a license is to be signed the optionally already existing, and probably obsolete signature is excluded so that the new signature can overwrite the old one. That way there is no need to remove first the signature feature before calculating the new signature.

        Note, however, that the message digest algorithm is also stored in he license in a STRING feature named signatureDigest. This feature is included into the signature creation process. In case the message digest algorithm is not the same for the new signature as it was for the old one when a license is resigned, then the signatureDigest feature should be set to be the name of the new message digest algorithm before calling unsigned(). This is actually done by the method sign(PrivateKey, String). The recommended way to sign a license is to call sign(PrivateKey, String), so client code should not really care about this nuisance, unless they chooses to create the signature their own way.

        When the license signature is verified the signature again is excluded and can be compared to the calculated one. This is done by the methods isOK(byte[]) and isOK(PublicKey).

        Returns:
        the byte array containing the license without the licenseSignature named signature feature.
      • add

        public void add​(byte[] signature)
        Add the signature to the license as a feature named licenseSignature.
        Parameters:
        signature - the signature itself.
      • getSignature

        public byte[] getSignature()
        Get the signature of the license. The signature of a license is stored in the license as a BINARY feature named licenseSignature. This method retrieves the feature and then it retrieves the value of the feature and returns the raw value.
        Returns:
        the electronic signature attached to the license.