Class License
- java.lang.Object
-
- javax0.license3j.License
-
public class License extends Object
A license describes the rights a certain user has. The rights are represented byFeature
s. 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.
-
-
Nested Class Summary
Nested Classes Modifier and Type Class Description static class
License.Create
Inner class containing factory methods to create a license object from various sources.
-
Method Summary
All Methods Instance Methods Concrete Methods Modifier and Type Method Description void
add(byte[] signature)
Add the signature to the license as a feature namedlicenseSignature
.Feature
add(Feature feature)
Add a feature to the license.UUID
fingerprint()
Get the fingerprint of a license.Feature
get(String name)
Get a feature of a given name from the license ornull
if there is no feature for the name in the license.Map<String,Feature>
getFeatures()
Returns the features of the license in a map.UUID
getLicenseId()
Get the license identifier.byte[]
getSignature()
Get the signature of the license.boolean
isExpired()
Checks the expiration date of the license and returnstrue
if the license has expired.boolean
isOK(byte[] key)
SeeisOK(PublicKey)
.boolean
isOK(PublicKey key)
Returns true if the license is signed, and the authenticity of the signature can be checked successfully using the key.byte[]
serialized()
Get the license serialized (not standard Java serialized!!!) as a byte array.void
setExpiry(Date expiryDate)
Set the expiration date of the license.UUID
setLicenseId()
Generates a new license identifier.void
setLicenseId(UUID licenseId)
Set the UUID of a license.void
sign(PrivateKey key, String digest)
Sign the license.String
toString()
Converts a license to string.byte[]
unsigned()
Get the license as abyte[]
without the signature key.
-
-
-
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 ornull
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 returnstrue
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 specifiedexpiryDate
. 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:
- Add the digest algorithm string to the license as a feature. The feature name is
signatureDigest
(name is defined in the constantDIGEST_KEY
in this class). - The license is converted to binary format
- A digest is created from the binary license using the message digest algorithm named by the
digest
parameter - The digest is encrypted using the key (which also has the information about the algorithm).
- 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 signaturedigest
- the name of the digest algorithm- Throws:
NoSuchAlgorithmException
- this exception comes from the underlying encryption libraryNoSuchPaddingException
- this exception comes from the underlying encryption libraryInvalidKeyException
- this exception comes from the underlying encryption libraryBadPaddingException
- this exception comes from the underlying encryption libraryIllegalBlockSizeException
- this exception comes from the underlying encryption library
- Add the digest algorithm string to the license as a feature. The feature name is
-
isOK
public boolean isOK(byte[] key)
SeeisOK(PublicKey)
.- 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 returnsfalse
.
-
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)
.
-
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. UsuallySHA-512
. It can actually beMD5
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 methodsetLicenseId()
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 inBINARY
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 abyte[]
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 namedsignatureDigest
. 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 thesignatureDigest
feature should be set to be the name of the new message digest algorithm before callingunsigned()
. This is actually done by the methodsign(PrivateKey, String)
. The recommended way to sign a license is to callsign(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[])
andisOK(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 namedlicenseSignature
.- 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 aBINARY
feature namedlicenseSignature
. 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.
-
-