My point is not build Fort Knox, but to avoid the support call because for some reason the user changed his MAC and that broke my app. The key left in two or three not obvious places in the registry will nicely “tag” the machine.
The issue I am having is that I have attempted to use Windows WMI service to get information about the machine in question. So I can request the Bios Serial, Hard Drive serial, Windows Key, etc. It all sounds good. The first problem I discovered is that if someone inserts a thumb drive, Windows returns the serial number of the thumb drive and NOT the hard drive. So I removed that. Then I thought I was OK. But customers still had problems. The hash would change randomly. So I put extra code in to see what was changing. It turns out - it’s not consistent and not consistent between users either. Sometimes WMI returns all the proper values and sometimes it does not. It might not return a value for Bios Serial number. Then other times it will. So another user, it might not return a value for the Windows Key. Other times it will.
I don’t want to use the MAC address because sometimes people use WiFI, other times that’s turned off and they use ethernet - all on the same machine. The MAC address can change and vary. So it’s not good.
It’s not that I am trying to build Fort Knox. I just want a way that will work and stay consistent! WMI is NOT providing that. That’s the issue.
I believe adding two or three keys in strategic places in the register with your own serial number is both easy and reliable.
Having played briefly, some BIOSs have no serial number, some motherboards do not have a serial number. It is easy though to get the boot drive serial number with DIR or VOL. WMI/WMIC often seems inconsistent across OS versions.
Problem with volume serial number is if someone changes out their hard drive. Then they have to get a new license key. I like the concept of getting things like I request:
Bios Serial Number
If I could consistently get this information it would work. I don’t care if there’s no bios serial number. Fine. Because I have other items I’m using. But the same machine will sometimes report a bios serial number and other times it won’t. Windows WMI is awful. The only redeeming grace I have is that I am able to tell my customers that a service in Windows that Microsoft wrote is not functioning properly.
So I’m thinking of simply generating a UUID using some of the code here and then stuffing that into the registry some place as Michel suggested and then using that as my identifying key that ties the license key to the particular machine.
The question is - where’s a good “strategic” place to stick it in the registry…
I have been looking for such strategic areas without breaking anything.
On Windows I would create subfolders in
but my absolute preference is HKEY_CLASSES_ROOT
It contains so many keys, who is going to wonder what a folder lost in there with an esoteric name is doing ?
To see all available places, press Window key(Option)-R, then type
I am currently working on the same idea to implement a 30 days trial on Mac. I don’t want to manage temporary license keys or call home. Three different hidden files scattered in the system tree in unassuming places should be enough to store the countdown, and if the user deletes and reinstalls the app, the three files will indicate the trial has expired.
Michel… a few years ago, I developed a “system” that did exactly what you are talking about, it stored encypted keys in 3 places on the users computer, and at all times 2 of the 3 had to match, and it 2 matched and one didn’t, the mis-match was “corrected”
However, a user on this forum (I forget who), told me he could crack that in 3 seconds… and proceeded to do so. He had some “spy” tool that monitored all file changes in real time, so when my app fired up, this tool showed him exactly where and what files where involved.
I have since abandoned that in favor of a method that stores the information right out in the open as an encrypted string inside a “config/plist/ini” type file. When the app is fired up for the first time, it sees this string does not exist, so it is created, with info about the machine, and random serial number, and a hardcoded private key, as well as the date. If/when the user decides to register, it stores his passkey (provided by me). the algorithm then takes the passkey and the original encrypted string, and validates them to determine if the app is properly registered. Attempting to copy the config/plist/ini file to another computer will not work as the machine id’s don’t match anymore, at which point the system generates a totally new set of keys for that machine, invalidating the provided passkey.
So far this method seems to work, as there is no attempt to “hide” files (which MAY cause issues with future OS releases). So far I have had only a few people need help because the system “failed”, and usually it was because they bought new hardware, or reformatted their computer.
Oh… .and my new method is cross platform, as I use a “custom” INI like format to store my config data
I have no doubt that anything can be cracked, with the proper tools and competences. My concern is not to be 500% bullet proof, but to be statistically solid enough for regular prospects not to install the demo time and again.
Incidentally, that exactly what people do with Avast, in spite of them requiring the user to register on their web site. Any free address is good to get a new one year free.
Thank you for your suggestion, though. Good food for thought.
Just catching up on this thread and reading the last two posts.
I handle my 30 day trial in a really simple manner. I store a file that on the Mac/Linux begins with a “.” and on Windows is hidden. I store the file in some obscure place. And I name it something that means something to me but has no meaning to anybody else. I then store in that file the current time in seconds. That’s it. When the user starts the app, I check to see if the current time in seconds minus the time stored in the file is less than 30 days. If it is, I allow the user to continue.
Yes, I know with a file monitoring tool, this would be VERY simple to crack. But I figure if someone wants to work that hard to not pay me for my software, then oh well. They get nagged about it being a demo every time they start. It’s simple, the file and it’s contents mean nothing to anyone by themselves but it works. I know it’s not the best or bulletproof but sometimes simplicity is all you need.
Dave, your method does sound interesting.
I’m considering developing an alternate way to offer the demo like with a code that I generate that would give them a demo period of however long I want to specify. I have some instances, like a large potential customer who needs more than 30 days. So lots of ways to skin the proverbial cat.
Jon, if you were to tie in the expiration date into the key you would be able to offer longer trial periods to those who need it. It would be a cleaner solution too, the key would have a permanent end date instead of being able to be used for 30 days on a clean computer later.
Best of all you wouldn’t have to hide files around the user’s computer!
[quote=264829:@Tim Parnell]Jon, if you were to tie in the expiration date into the key you would be able to offer longer trial periods to those who need it. It would be a cleaner solution too, the key would have a permanent end date instead of being able to be used for 30 days on a clean computer later.
Best of all you wouldn’t have to hide files around the user’s computer![/quote]
Agreed. They don’t use a key at all right now for the trial. But I do like this idea. I just started using this method back like 5 or 6 years ago when I first started writing my app. I’ve learned so much since then! Still have much to learn moving forward as well.
But I think I just might do something like this for my next major release. Will help me get a better handle on who’s using the program in a legitimate demo fashion as well since they need to request a demo key…
This is not in answer to the OP, but might be of interest. You could use the shell command uuidgen and grab the result:
Seems to work.
For the evaluation version of Fonts Manager, I have finally given up entirely on the keys and hidden files.
I will use my web service that the app calls when it starts, to verify how many days it still has. That way even if the user takes back his clock the count remains right. That also allows me to track the number of trials.
There will be a nag window reminding him it is an evaluation and how many days remain.
At the end of the trial, he is left with a window that offers either to purchase on the MAS, or to buy a license key. When the user clicks on the Paypal button it starts a timer that polls the license server. The moment payment is complete, the app is updated with the license information and activated.
At the same time, a mail is sent to the user with license information.
If the user has no internet connection or your server is down the app can’t be used right?
[quote=270367:@Albin Kiland]If the user has no internet connection or your server is down the app can’t be used right?
Just curious :)[/quote]
Indeed, the app requires an Internet connection, and if the server is down, it cannot run.
Today, Internet is assumed by a growing number of apps anyway, and since the evaluation program will be downloaded in the first place, it would make little sense not to have access to Internet afterward.
The server I currently use has been down about 2 hours total in 3 years, so I am not awfully worried.
Of course I will tell on the web site that the evaluation app needs Internet to run.
The registered app won’t need Internet, as the license key is stored on the machine anyway.
And with that you’ve earned my gold stamp of approval
Thank you Tim
[quote=172843:@Kem Tekinay]Here is a function that will work across platforms:
Protected Function GenerateUUID() As String
// From http://www.cryptosys.net/pki/uuid-rfc4122.html
// Generate 16 random bytes (=128 bits)
// Adjust certain bits according to RFC 4122 section 4.4 as follows:
// set the four most significant bits of the 7th byte to 0100’B, so the high nibble is ‘4’
// set the two most significant bits of the 9th byte to 10’B, so the high nibble will be one of ‘8’, ‘9’, ‘A’, or ‘B’.
// Convert the adjusted bytes to 32 hexadecimal digits
// Add four hyphen ‘-’ characters to obtain blocks of 8, 4, 4, 4 and 12 hex digits
// Output the resulting 36-character string “XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX”
dim randomBytes as MemoryBlock = Crypto.GenerateRandomBytes(16)
randomBytes.LittleEndian = false
// Adjust seventh byte
dim value as byte = randomBytes.Byte(6)
value = value and &b00001111 // Turn off the first four bits
value = value or &b01000000 // Turn on the second bit
randomBytes.Byte(6) = value
// Adjust ninth byte
value = randomBytes.Byte(8)
value = value and &b00111111 // Turn off the first two bits
value = value or &b10000000 // Turn on the first bit
randomBytes.Byte(8) = value
dim result as string = EncodeHex(randomBytes)
result = result.LeftB(8) + “-” + result.MidB(9, 4) + “-” + result.MidB(13, 4) + “-” + result.MidB(17, 4) + _
“-” + result.RightB(12)
How to change that, to use it with the new Xojo-Framework? Should return a Text-Value! Xojo.Core.MemoryBlock don’t know the Byte-Function and Text hasn’t the LeftB/RightB Function. Also the Structures of the Native-Version from @Kem Tekinay .
I need bring this topic back to life for a moment.
in the code posted WAY up near the top (when the topic was still about UUID )
there are these lines
#If TargetWin32 Const kLibName = "win32.Rpcrt4" Soft Declare Function UUIDCreate Lib kLibName alias "UuidCreate" ( ByRef uuid As WindowsUUID ) As Integer Soft Declare Function UUIDToString Lib kLibName alias "UuidToStringA" ( ByRef inUUID As WindowsUUID, ByRef outString As CString ) As Integer Dim uuid As WindowsUUID Dim out As CString result = out result = result.DefineEncoding( Encodings.UTF8 ) result = result.Uppercase #EndIf
If this is changed to TargetWINDOW will it work for 64-Bit … or does it need to reference something other than win32.Rpcrt4?
And I ASSUME changing TargetCocoa to TargetMacOS will work for both 32/64 bit?
I have an app (a class) that needs to run any environement (except iOS) that Xojo currently supports, and it must have a generated UUID
No reason to use declares. Scroll up a bit, I posted code to do it in pure Xojo. If you need new framework support, I can get that for you too.