home *** CD-ROM | disk | FTP | other *** search
Text File | 1995-04-11 | 11.8 KB | 497 lines | [TEXT/KAHL] |
-
- // ****************************************************************
- //
- // Copyright 1995 Digital Money, Inc.
- // You may use this source code in your own applications.
- //
- // *******************************************************************
- //
- // Supplemental routines for use with Digital Money AutoPay Module.
- // These routines were written for Think C 5.0
- // but should be immediately useable with other C environments.
-
- // Feel free to use these routines in you own applications.
- // See the AutoPay manual, Chapter 4, for more information.
-
- // This file uses ANSI routines.
-
- // Updated April 5, 1995.
- // *******************************************************************
-
- // *******************************
- // THINGS YOU NEED TO PERSONALIZE:
- // *******************************
-
- // Personalize the following three strings:
-
- #define kTheCryptoKey "Put your crypto key here!"
- #define kYourProgramName "YourProgramNameHere"
- #define kOwnerResource 'xYxn' // This should match your
- // application's owner resource
- // If you don't know what this is,
- // choose a random 4-char string.
- #include <Folders.h>
- #include <Files.h>
- #include <Script.h>
-
- // The keyType structure. See the description below.
-
- typedef struct
- {
- char name[60];
- char verificationCode[60];
- char serialNumber[30];
- } keyType;
-
- // *******************
- // Function prototypes
- // *******************
-
- OSErr readKeyFromDisk (keyType *key);
- OSErr writeKeyToDisk (keyType *key);
- Boolean isProgramRegistered (void);
- char *myEncrypt (char *inputString, char *cryptoKey);
- OSErr saveProgramAsRegistered (char *theName);
- OSErr saveSerialNumber (char *theSerialNumber);
-
-
- Boolean isProgramRegistered (void)
- {
- keyType theKey;
- char cryptoKey[50], whatItShouldBe[80];
- OSErr iErr;
-
- // EXPLANATION:
- //
- // This is a pretty straightforward locking/unlocking mechanism that you can use
- // in your program to see whether a program has been registered (i.e. payed for)
- // or not.
-
- // A brief description follows, but for more details, you should see
- // your AutoPay Developer's Manual.
-
- // What happens is this. The program opens a "key file" which is stored
- // in the preferences folder. The Key File has three components:
-
- // The registration name : the name of the user who paid for program
-
- // The verification code : a special code that is specific to
- // to the registration name. This proves the
- // registration name hasn't been tampered with.
-
- // The serial number
-
-
-
- iErr=readKeyFromDisk(&theKey);
-
- if (iErr)
- {
- // add your own error handling here if desired
- }
-
- if (strlen((char*)theKey.name)==0)
- {
- // Either the key file doesn't exist or the name has been tampered
- // with. So treat this as an unregistered copy.
-
- return (false);
- }
-
- // A name *does* exist. Now the program looks at the verification code.
- // There is some, *unobvious* cryptographic relationship between the name and
- // the verification code, but only you as the developer knows it. This stops
- // hackers from examining an officially registered copy of your app and figuring
- // out how to write a "correct" result string based on a seed string of his choice.
-
- if (strlen((char*)theKey.verificationCode)==0)
- {
- return (false);
- }
-
- strcpy(cryptoKey,kTheCryptoKey);
-
- // Feed the name into the encryption routine to find out what the
- // verification code *should* be. Then see if it's a match.
-
- strcpy((char*)&whatItShouldBe, myEncrypt((char*)&theKey.name,cryptoKey) );
- if ( strcmp (
- whatItShouldBe, // If the resultString is
- &theKey.verificationCode // identical to what you'd expect to get
- ) == 0 ) // given your program's cryptoKey,
-
- {
- return(true); // then this is a valid, registered copy
- }
- else
- {
- return(false); // ...otherwise it isn't
- }
- }
-
- OSErr saveSerialNumber (char *theSerialNumber)
- {
- keyType theKey;
-
-
- readKeyFromDisk(&theKey);
- strcpy((char*)&theKey.serialNumber,theSerialNumber);
- writeKeyToDisk(&theKey);
- }
-
-
-
- OSErr saveProgramAsRegistered (char *theName)
- {
- OSErr iErr;
- keyType theKey;
- char *theResult;
- char cryptoKey[50];
-
- // First the program stores the name string in the appropriate place.
-
- iErr=readKeyFromDisk(&theKey);
- if (iErr)
- return (iErr);
-
- // Next it stores the Verification Code, which is encrypted based on your
- // cryptoKey. See the Digital Money manual for more information.
-
- strcpy(cryptoKey,kTheCryptoKey);
- strcpy ((char*)&theKey.verificationCode, myEncrypt(theName,cryptoKey) );
-
- strcpy((char*)&theKey.name,theName);
- iErr=writeKeyToDisk(&theKey);
- if (iErr)
- return (iErr);
-
- }
-
-
- char *myEncrypt(char *inputString, char *cryptoKey)
- {
- long numCharsInInput;
- int cryptoCharToUse,i;
- char charToAdd;
- char *outputString;
-
- // Given an input string and a cryptoKey (know only to you)
- // this routiner spits out an encrypted version of the input
- // string. Later, you'll be able to compare say, a user's name
- // and it's encrypted version to make sure the user's name hasn't been
- // tampered with.
-
- outputString=NewPtr(strlen(inputString)+1);
-
- numCharsInInput=strlen(inputString);
- cryptoCharToUse=0;
- *outputString='\0';
-
- for (i=0; i<=numCharsInInput-1; i++)
- {
-
- charToAdd=(inputString[i]^cryptoKey[cryptoCharToUse])+28; // ^ is exclusive OR
-
- charToAdd=charToAdd%33; // the remainder of the number after divided by 33
- charToAdd=32+charToAdd;
- outputString[i]=charToAdd;
-
- cryptoCharToUse++;
- if (cryptoCharToUse>strlen(cryptoKey)-1)
- cryptoCharToUse=0;
- }
-
- outputString[i]='\0'; // make sure the output string is terminated with a null
-
- return (outputString);
- }
-
-
-
- OSErr readKeyFromDisk (keyType *key)
- {
-
- OSErr myErr;
- short myVRef, i;
- long myDirID;
- FSSpec mySpec;
- char myName[25];
- int myRef;
- Handle myHandle;
- int myRefNum, version;
- long len;
- long myLen[6];
-
- // find the "key" file in the system
-
- strcpy(myName,kYourProgramName);
- strcat(myName," Key");
-
- // The "key file" will be stored in the Preferences folder
- // within the System folder
-
- myErr=FindFolder(kOnSystemDisk,kPreferencesFolderType,kDontCreateFolder, &myVRef, &myDirID);
-
- if (myErr==noErr)
- myErr=FSMakeFSSpec(myVRef, myDirID, CtoPstr(myName), &mySpec);
-
- // If no "key file" exists, return a null key.
- // This will happen the first time the user wants to register.
-
- if (myErr==fnfErr)
- {
- key->name[0]='\0';
- key->verificationCode[0]='\0';
- key->serialNumber[0]='\0';
- return(noErr);
- }
-
- if (myErr==noErr)
- myRefNum=FSpOpenDF(&mySpec, fsRdWrPerm, &myRef);
- else if (myErr!=eofErr) return(myErr); // error check
-
-
- myErr=SetFPos(myRef, fsFromStart,0);
-
- if ((myErr!=noErr) && (myErr!=eofErr))
- return(myErr); // error check
-
- // Check the version number of the key file.
- // This really has no use now, but may or may not come in handy in
- // in the future, if you ever decide to change the file format of
- // the key file.
-
- len=2;
- if (myErr==noErr)
- {
- myErr=FSRead(myRef, &len, &version);
- }
- if (version!=1)
- myErr=eofErr; // if this is not version 1, just pretend file doesn't exist
-
- len=sizeof(*key);
-
- if (myErr==noErr)
- {
- myErr=FSRead(myRef, &len, key);
- }
-
-
- if ((myErr) && (myErr!=eofErr)) return(myErr); // error check
-
- FSClose(myRef);
-
- return(noErr);
-
- }
-
- OSErr writeKeyToDisk (keyType *key)
- {
- OSErr myErr;
- short myVRef, i;
- long myDirID;
- FSSpec mySpec;
- char myName[25];
- int myRef,scrapInt;
- int myRefNum, myVol;
- long len,fLength=0;
-
- strcpy(myName,kYourProgramName);
- strcat(myName," Key");
-
- myErr=FindFolder(kOnSystemDisk,kPreferencesFolderType,kDontCreateFolder, &myVRef, &myDirID);
-
- if (myErr==noErr)
- myErr=FSMakeFSSpec(myVRef, myDirID, CtoPstr(myName), &mySpec);
-
- if (myErr==fnfErr)
- {
- myErr= FSpCreate(&mySpec, kOwnerResource, 'pref', smSystemScript);
- fLength=0;
- }
-
- if (myErr==noErr)
- myRefNum=FSpOpenDF(&mySpec, fsRdWrPerm, &myRef);
-
-
- if (myErr==noErr)
- {
- myErr=SetFPos(myRef, fsFromStart, 0); // write at beginning
- }
-
- // Write the version number of the key file
- // for future upgrade capability. This is version 1.
-
- len=2;
- scrapInt=1;
- if (myErr==noErr)
- {
- myErr= FSWrite (myRef, &len, &scrapInt);
- fLength+=len;
- }
-
- // write the actual key data structure
-
- len=sizeof(*key);
- if (myErr==noErr)
- {
- myErr= FSWrite (myRef, &len, key);
- fLength+=len;
- }
-
- myErr=SetEOF(myRef, fLength);
- if (myErr) return(myErr);
-
- if (myErr==noErr)
- {
- myErr=GetVRefNum(myRef, &myVol); // find volume file is on
- }
-
- if (myErr==noErr)
- {
- FSClose(myRef);
- myErr=FlushVol(nil, myVol); // ... and flush it
- if (myErr) return(myErr);
- }
-
- return(myErr);
- }
-
-
- /********************************/
- // drawSplashScreen //
- /*******************************/
-
- void drawSplashScreen (int whichColorPictToUse, int whichBWPictToUse)
- {
-
- GrafPtr oldPort;
- Boolean userReacts, hasColor=false;
- SysEnvRec sysEnv;
- Rect r,winRect,textBox;
- PicHandle thePict;
- int screenWidth,screenHeight,pictWidth,pictHeight,winLeft,winTop;
- WindowPtr window;
- short oldFont,oldSize,curPnMode;
- EventRecord event;
- keyType theKey;
- char output[100];
-
- #define SysEnvironsTrap 0xA090
- #define UnknownTrap 0xA89F
-
- GetPort(&oldPort);
-
- // First check to see if the computer has color display or not.
- // This will help us decide whether to draw the color picture
- // or the B&W picture.
-
- if ((long)NGetTrapAddress(SysEnvironsTrap, OSTrap) != (long)NGetTrapAddress(UnknownTrap, ToolTrap))
- {
- SysEnvirons(1, &sysEnv);
-
- // Check graphic's device depth
- if ((*((*((GDHandle)GetGDevice()))->gdPMap))->pixelSize > 1)
- {
- hasColor = sysEnv.hasColorQD; // Does it have color?
- }
- }
-
- if (hasColor)
- thePict=GetPicture(whichColorPictToUse);
- else
- thePict=GetPicture(whichBWPictToUse);
-
- r = (*thePict)->picFrame;
-
- pictWidth = r.right - r.left; // calculate width of picture
- pictHeight = r.bottom - r.top; // calculate height of picture
-
-
- screenWidth =(screenBits.bounds).right; // calculate width of screen
- screenHeight =(screenBits.bounds).bottom; // calculate height of screen
-
- // Center the splash window on the screen:
-
- winLeft=(screenWidth/2)-(pictWidth/2);
- winTop=(screenHeight/2)-(pictHeight/2);
- SetRect(&winRect,winLeft,winTop,winLeft+pictWidth,winTop+pictHeight);
-
- // make a new, temporary window, just big enough to hold your
- // splash screen picture
- window = NewWindow(nil,&winRect,"\p",true,plainDBox,(WindowPtr)-1,false,0);
-
- SetPort(window);
- DrawPicture( thePict, &(window->portRect) );
-
- // Now draw your text ON TOP OF the picture.
-
-
- TextFont(applFont);
- TextFace(bold);
-
- readKeyFromDisk(&theKey);
-
- if (!isProgramRegistered())
- {
-
- strcpy(output,"This program is not registered.\rYou can register immediately with Digital Money™.\rSee the Apple menu.");
-
- // You may want to change the coordinates where the text box is overlaid
- // on picture window:
-
- TextSize(11);
- SetRect(&textBox,window->portRect.left+2,window->portRect.bottom-80,window->portRect.right-2,window->portRect.bottom-30);
- TextBox(output,strlen(output),&textBox,teJustLeft);
-
- }
- else
- {
-
- sprintf(output,"This copy is registered to %s.",(char*)&theKey.name);
-
- TextMode(srcBic); // reverse out the text you're about to draw
-
- // You may want to change the coordinates where the text is
- // "reversed out" of window:
-
- MoveTo(2,window->portRect.bottom-45);
- TextSize(10);
- DrawText(output,0,strlen(output));
- if (strlen((char*)&theKey.serialNumber))
- {
- sprintf(output,"Serial Number %s",(char*)&theKey.serialNumber);
- MoveTo(2,window->portRect.bottom-30);
- }
- }
-
- SelectWindow(window);
-
-
- // wait for the user to click the mouse or hit a key...
-
- userReacts=false;
- do
- {
- if (WaitNextEvent(everyEvent, &event, 20, nil))
- {
- switch (event.what)
- {
- case mouseDown:
- case keyDown:
- case autoKey:
- userReacts=true;
- break;
- default:
- userReacts=false;
- break;
- }
- }
- }
- while (!userReacts);
-
- HideWindow(window);
- DisposeWindow(window);
- ReleaseResource(thePict);
- }
-