Keep in mind that the weakest spot with your licensing system will be your code.
Therefore, make it not too easy for the casual cracker to modify your app in order to disable your license verification.
Here are a few ideas:
Do not store the public key in one piece, so that a cracker can not simply find and replace that key with his own key, enabling him to add his own license files then. Instead, split the data up into multiple pieces, maybe even generating some of it instead of it appearing clear in the code.
Similarly, obscure the blacklist data so that a cracker can't simply find the table and nullify its entries, then use an old license file that you mean to have blacklisted.
A cracker with debugging skills will find your verification code and simply disable the checks for the validity of the license signature, or will even find the code calling the function and replace it with code that either skips it or returns his own dictionary with fake values from the license. To make this crack harder, call the verification code from multiple places, using different data, e.g. a valid but blacklisted license, to see if you get an error and not the same fake dictionary. Do such calls in places that are later invoked, to make a cracker believe that he succeeded quickly. Of course, the biggest problem with this approach is that it may be easy to learn that the verify function is called from multiple places, so make it difficult for the cracker to figure out the circumstances. The more work you put into this the more likely you get the cracker to give up, or even make him believe that he's done when he isn't.
Do not tease the cracker if you detect that your code got modified. A random crash is better. Teasing the cracker will only get his ego attacked, and then you really lose, usually.
A more detailed guide can be found here: http://www.tempel.org/UsingAquaticPrime