! CIPHER -- Basic subroutine to encode or decode a string of ! up to 504 characters with a user-supplied password ! Hytek International, Inc. / P.O. Box 670 / Joplin, MO 64802 ! Created by Brad Horine. All rights are reserved to the author. ! Donated to Alpha Micro Users' Society (AMUS) on 29 January 1986 ! No party, including but not limited to Brad Horine, Hytek International ! Inc., or Alpha Micro Users' Society, may be held liable for any damages, ! whether actual or consequential, resulting from the use of this routine. ! Permission granted to copy and use freely, provided that all notices ! and disclaimers remain intact. ! ! ************************************************************************ ! * NOTE: Any use of this product for commercial gain, including but not * ! * limited to inclusion of this routine in whole or in part with * ! * any commercial hardware or software, is expressly forbidden, * ! * unless prior written authorization is obtained from the * ! * author. * ! ************************************************************************ ! ! Variables: ! MAP1 C'FILENAME,S,24 ! MAP1 C'PASSWORD,X,512 ! MAP1 C'BUFFER,X,512 ! MAP1 C'LENGTH,F ! MAP1 C'CONTROL,F ! MAP1 C'WORKBUFF,X,512 ! ! ********** ENCODING DATA ********** ! ! Input: ! C'FILENAME Filename to be created, which will contain the ! encrypted data ! C'PASSWORD Encryption key supplied by user ! C'BUFFER Data to be encrypted (504 characters max.) ! C'LENGTH Number of valid characters in C'BUFFER ! C'CONTROL value of -1 ! ! Output: Data is encrypted into FILENAME with a verification ! code added ! ! ********** DECODING DATA ********** ! ! Input: ! C'FILENAME Filename containing data to be decoded ! C'PASSWORD Encryption key supplied by user ! C'CONTROL value of 0 ! ! Output: Unencrypted data is returned in bytes 1 thru C'LENGTH ! of C'BUFFER ! ! ********** ERRORS ********** ! ! Errors are returned to the calling program as codes contained in ! the variable C'CONTROL as follows: ! ! 1 -- C'FILENAME was not found when trying to decode ! 2 -- C'FILENAME already existed when trying to encode ! 3 -- C'FILENAME was found, when trying to deocde, but was not in ! the correct format (ie, was not random or was not exactly ! 1 block in length) ! 4 -- C'PASSWORD given to decode data was not the same as the ! one used to encode the data, OR data was not encoded ! 5 -- C'CONTROL was not -1 or 0 ! 6 -- C'LENGTH was invalid (less than 1 or greater than 504) ! ! ! Please note that neither the PASSWORD nor the original data are ! stored anywhere on the disk. This helps to make the encrypted ! data more secure. ! ! Since the routine pads the unused space in C'BUFFER with random ! data before encoding it, there IS a remote chance that the ! 'recognition' pattern of "<DEL>cIpHeR" COULD appear in the ! uncoded data. The chances of this are approximately 1 in ! 9,223,370,000,000,000,000 (1 in 256^7). This still would ! not pose a problem, because the decoding routine will remove ! the first occurrence of the recognition pattern, and the second ! occurrence will ALWAYS be in the 'unused' area of C'BUFFER. ! Think it through for yourself if you have any doubts about this. ! Also, the 'security' of the encoded data is in direct relation ! to the length of the password. That is, a 1-character password ! would take 256 attempts to crack, while a 2-character one takes ! 65,536 tries, on up to a 512-character password taking 256^256 ! tries, a bigger number than an Alpha Micro can even store! ! ! One possible use of this routine would be as part of a LOGON-type ! security system, where data pertaining to a user's security ! level, disk account, etc. is stored in a file with the same ! name as his user-id name, and is decoded by using his password. ! !************************************************************************** ! CIPHER: ! data encryption routine ! ! check for correct parameters ! IF C'CONTROL<>0 AND C'CONTROL<>-1 THEN & C'CONTROL=5: RETURN IF C'CONTROL=-1 AND (C'LENGTH<1 OR C'LENGTH>504) THEN & C'CONTROL=6: RETURN LOOKUP C'FILENAME, C'FOUND IF C'FOUND=0 AND C'CONTROL=0 THEN & C'CONTROL=1: RETURN IF C'FOUND<>0 AND C'CONTROL=-1 THEN & C'CONTROL=2: RETURN IF C'FOUND<-1 OR C'FOUND>0 THEN & C'CONTROL=3: RETURN IF C'FOUND=0 AND C'CONTROL=-1 THEN & ALLOCATE C'FILENAME,1 IF C'CONTROL=0 THEN & OPEN #9991, C'FILENAME, RANDOM, 512, REC9991: & REC9991=0: READ #9991, C'BUFFER: CLOSE #9991 ENCODE: IF C'CONTROL=0 THEN GOTO DECODE ! ! insert verification code into raw data at a random spot ! RANDOMIZE IF C'LENGTH=504 THEN GOTO NOFILL FOR C'FILL = C'LENGTH+1 TO 512 C'BUFFER[C'FILL;1] = CHR(INT((RND(0)*512)+1)) NEXT C'FILL NOFILL: C'SPLIT = INT((RND(0)*504)+1) C'BUFFER[C'SPLIT+8,512] = C'BUFFER[C'SPLIT,504] C'BUFFER[C'SPLIT;8] = CHR(127)+"cIpHeR"+CHR(C'LENGTH) DECODE: ! ! perform the encryption/decryption algorithm on the data in C'BUFFER ! C'PWLEN = INSTR(1,C'PASSWORD,CHR(0)): C'PWPOINT = 0 FOR C'BPOINT = 1 TO 512 C'PWPOINT = C'PWPOINT + 1 IF C'PWPOINT > C'PWLEN THEN C'PWPOINT=1 C'WORKBUFF[C'BPOINT;1] = & CHR(ASC(C'BUFFER[C'BPOINT;1]) XOR ASC(C'PASSWORD[C'PWPOINT;1])) NEXT C'BPOINT ! ! if we are encoding, then write the pattern to disk and exit ! IF C'CONTROL=0 THEN GOTO VERIFY OPEN #9991, C'FILENAME, RANDOM, 512, REC9991 REC9991=0: WRITEL #9991, C'WORKBUFF: CLOSE #9991 C'WORKBUFF = SPACE(512): C'CONTROL = 0 : RETURN ! ! IF DECODING, verify that correct password was used by checking ! for verification code ! VERIFY: C'VERPOS = INSTR(1,C'WORKBUFF,CHR(127)+"cIpHeR") IF C'VERPOS = 0 THEN C'CONTROL=4: RETURN ! ! verification passed -- remove verification code and return ! C'LENGTH = ASC(C'WORKBUFF[C'VERPOS+7;1]) IF C'VERPOS=1 THEN C'BUFFER[1,504]=C'WORKBUFF[9,512]: & C'CONTROL=0: RETURN C'BUFFER[1,C'VERPOS-1] = C'WORKBUFF[1,C'VERPOS-1] C'BUFFER[C'VERPOS,504] = C'WORKBUFF[C'VERPOS+8,512] C'WORKBUFF = SPACE(512): C'CONTROL=0: RETURN ! ! end of routine !