Let's state things clearly: there is such a thing called asymmetric encryption. There is another, completely different thing called digital signatures. Whenever you see some text that talks about "decryption with the public key", then that text is really talking about signatures, and is trying to explain signatures as if it was some kind of encryption, which:
- works only for a specific algorithm called RSA;
- does not a actually work for RSA, when looked at closely.
So it is much better to talk to things under their true names.
What a signature can do for a license file is to guarantee that a piece of data is genuine:
The vendor owns a key pair that consists in elements that are mathematically linked together: the public key and the private key. They are called that way because though they are facets of the same mathematical object, there is no known method to rebuild the private key from the public key; thus, the public key can be made public, since this does not reveal the private key.
The vendor uses the private key to compute a signature on the license file. The signature generation algorithm uses as inputs the data to be signed (license file contents) and the private key, and outputs the signature.
The application verifies that the signature is correct. The application can do that because it embeds a copy of the vendor's public key: the signature verification algorithm uses as inputs the data which was signed (the license file contents), the public key, and the signature; and that algorithm returns "that's OK" when the three elements match.
By the magic of the cryptography in the signature algorithm, only the private key owner (the vendor) can produce signature values that the verification algorithm will accept as "correct" with regards to the vendor's public key. Outsider, who do not know the private key, cannot do that.
It is still up to the application to enforce whatever the license file says. What the signature on the license file guarantees is that the license file really comes from the vendor. The rest is up to the application.
Of course, signed license files do not really prevent piracy. The critical part, here, is that the application must still include a copy of the vendor's public key, verify the signature, and apply the rules contained in the license file. Someone who wants to copy the application and run it elsewhere may still do a bit of reverse engineering and do one of the following:
Replace the public key embedded in the application with his own public key, for which he has the corresponding private key, allowing him to produce his own fake license files that the application will blindly accept.
Patch the application code that checks the signature on the license file so that an invalid signature is accepted nonetheless. This is not hard to do; ultimately, in the compiled code, there is a conditional jump opcode that sees what the signature verification algorithm returned (a boolean value that says "signature is valid" or "signature is not valid") and jumps to the relevant piece of code. It suffices to replace that conditional jump with either a nop, or an unconditional jump.
Remove the whole license file processing code altogether. Wherever the application contains a call to the license-checking system, simply remove the call.
Since that kind of reverse engineering is easy, it would be wrong to imagine that a signed license file really prevents software piracy. What it helps with, though, is legal qualification. When some reverse engineering is involved, intent is made plain. The software pirate can no longer be casual about it; by altering the application code to circumvent the license file checks, he clearly demonstrates that he knows what he is doing. Depending on the jurisdiction, such a legal qualification can matter a lot when it comes to police raids and trials.
Your code appears to create a 512-bit RSA key, which is very weak. A 512-bit RSA key was cracked in 1999, with the computing power that was available to academics at that time (by "cracking" I mean "reconstructing the private key from the public key"). Nowadays, it can be done with a single desktop computers in a couple of months; alternatively, it can be done in a few days with about 75$ of rented computing power from some cloud vendor like Amazon.
Similarly, using MD5 as companion hash function (the RSA signature algorithm uses a hash function as additional element) will get you bad points, since that function is considered "broken" (actually, it can still be used securely in the context of RSA signatures, but one has to be careful about it, and it still looks bad during audits).
You seem to sign just the "expiry date", which makes your license files generic -- applicable to all application instances. This is problematic because it suffices of a single leak of a valid license file to allow everybody to use it. Usually, people who make signed license file design the file contents so that the signed data includes a unique identifier for the application instance: the application, when it installs on the computer, create a unique, random identifier, sends that to the vendor, and the vendor signs a license file that contains that identifier. That way, a license file can be made specific to each instance, and not usable to unlock any other instance. Alternatively (or complementarily), the license file may contain the customer name so that leakages can be traced back to the culprit (and thus, hopefully, deter wannabe leakers).