張東瀛
原載 自動化科技 1996 年 12 月 p.62-67(上) 自動化科技 1997 年 1 月 p.54-59(下)
REM ****************************************** REM * CHarades.BAS Version 2.0 * REM * 01-22-1986 * REM * By Tony Chang * REM * 06-22-1996 * REM * Writing in Quick BASIC 4.5 * REM * Tony Knowledge Engineering Lab * REM ****************************************** 以上為版權宣告及程式設計相關資訊 'EXIT Reminder 暫回DOS作業系統的檢知器。程式內因設有暫回DOS的功能 因此利用&H4E位址來偵測是否已執行本程式。使用者按Esc時,將&H4E內函值設 定為5,表示電腦已執行本程式 COLOR 15, 1: DEF SEG = &H30: MS% = PEEK(&H4E): DEF SEG IF MS% = 5 THEN CLS : BEEP: PRINT PRINT "CHarades 2.0 already installed, type EXIT to return": END END IF 程式開始執行時先檢查&H4E是否等於5,是的話,則提醒使用者打EXIT回本程式 若否,則繼續下一步,定義變數 A1$ = CHR$(68): A3$ = CHR$(97): A4$ = CHR$(109): A5$ = CHR$(101) A2$ = CHR$(114) 這些變數用來定義密碼所需的字母,如果直接使用字串定義,很容易用PCTools 等工具程式看出,所以先用字母的ASCII值來定義變數,再加以組合成密碼 此一變數為音樂響鈴,可用PLAY指令發聲 FATE1$ = "MB T180 O2 P2 P8 L8 GGG L2 E-" 利用剛才定義的變數設定密碼PK1$,至於PK2$可作為備用鑰匙或第二個密碼, 必要時也可再增加幾個KEY CODE,甚至建立密碼庫存放這些密碼 I = 1: KEY OFF: CLS : LOCATE , , 0, 14 PK1$ = A1$ + A2$ + A5$ + A3$ + A4$ + A5$ + A2$ PK2$ = PK1$ '本例只用一個密碼 從第line 14到line 18為密碼檢核常式,I值設定讓使用者可輸入三次,超過 三次未輸入正確密碼則結束程式。非法使用者有時會先找出密碼為幾位數,再進 行測試。此處使用DO ... LOOP 的目的即是讓非法使用者無法查覺密碼位數,以 增加篩檢困難度。 14 PRINT : PRINT : PRINT : ' PLAY FATE1$ IF I <= 3 THEN I$ = LTRIM$(STR$(I)) ANS$ = "": LOCATE 8, 10, 1: PRINT "Password" DO: SANS$ = INPUT$(1): ANS$ = ANS$ + SANS$ LOOP UNTIL ASC(SANS$) = 13 I = I + 1: PRINT : ANS$ = LEFT$(ANS$, 7) IF I > 3 THEN GOTO 16 ELSE GOTO 18 END IF END IF CLS : LOCATE 10, 12: PRINT "Incorrect password, permission denied." LOCATE 22, 7 PRINT "* * * By Tony Chang, Tainan, Taiwan, August 18, 1986 * * *" PRINT : END 16 IF NOT (ANS$ = PK1$ OR ANS$ = PK2$) THEN GOTO 14 18 IF NOT (ANS$ = PK1$ OR ANS$ = PK2$) THEN LOCATE 10, 10: PRINT "Incorrect password, try again please." SOUND 700, 1: GOTO 14 以上的密碼檢核常式,原先是以MBASIC寫成,後來改用QBASIC編譯成OBJECT CODE 就可在不同的程式呼叫。
50 CLS A6$ = CHR$(110): A12$ = CHR$(111): A15$ = CHR$(121): A16$ = CHR$(84) LOCATE 1, 1: PRINT "CHarades 1.0 Copyright " + A16$ + A12$ + A6$ + A15$ + " Lab 1992" IF A16$ <> "T" OR A6$ <> "n" OR A12$ <> "o" OR A15$ <> "y" THEN 50 以上是防止版權宣告遭他人篡改的措施 其次是設計以方向鍵操作的功能選單,使用者可以選擇「加密」「解密」「結束」 等功能,選項以紅底黃字顯示,項目少時,用方向鍵比較便捷,選單多時才用滑鼠操作 CLEAR : DIM M$(4): ECG$ = "MF L16O2ECG>CEG>CL32O2CDEFGAB>CDEFGAB>C" M$(1) = " 1: Charades " M$(2) = " 2: Reduction " M$(3) = " 3: Exit to DOS " FOR Y = 1 TO 3: LOCATE 2 * Y + 6, 30: PRINT M$(Y): NEXT Y LOCATE , , 0 Y = 1: MVE = NO: X = 1: Q$ = "" WHILE Q$ <> CHR$(13) LOCATE 2 * Y + 6, 30: COLOR 14, 4: PRINT M$(Y): COLOR 15, 1 Q$ = INKEY$: WHILE Q$ = "": Q$ = INKEY$: WEND IF LEN(Q$) = 2 AND ASC(RIGHT$(Q$, 1)) = 72 THEN MVE = YES: X = Y - 1: IF X = 0 THEN X = 3 END IF END IF IF LEN(Q$) = 2 AND ASC(RIGHT$(Q$, 1)) = 80 THEN MVE = YES: X = Y + 1: IF X = 4 THEN X = 1 END IF END IF 'Call DOS shell 這一段是利用SHELL指令設計暫回DOS功能,有時候忘記檔案放在那個目錄,或是臨時想 到DOS作業,便可按Esc跳出。&H4E用來存放程式辨識值 IF ASC(RIGHT$(Q$, 1)) = 27 THEN CLS : DEF SEG = &H30: H4E% = PEEK(&H4E): POKE &H4E, 5: SHELL DEF SEG = &H30: POKE &H4E, H4E%: DEF SEG : GOTO 50 END IF IF Q$ >= "1" AND Q$ <= "3" THEN X = VAL(Q$): MVE = YES IF MVE = YES THEN LOCATE 2 * Y + 6, 30: PRINT M$(Y): Y = X: MVE = NO WEND A$ = STRING$(1, " ")'定字串長度 IF Y = 1 THEN 110 IF Y = 2 THEN 370 IF Y = 3 THEN PLAY ECG$: CLS END 這一段是加密常式,先輸入要進行加密和加密後的檔名 110 CLS : BEEP LOCATE 7, 20: PRINT "ASCII (Binary) file -> Charade file" LOCATE 9, 20: INPUT "Source file name "; SFN1$: IF SFN1$ = "" THEN 110 LOCATE 11, 20: INPUT "Charade file name "; CFN1$: IF CFN1$ = "" THEN 110 再用 SUB 600 讓使用者選擇 1-99999 五位數作密碼,CD%是密碼值除以256後的餘數 GOSUB 600 打開檔案,將ASCII碼逐一讀入,經過編碼運算後存入新檔 OPEN SFN1$ FOR BINARY AS #1 OPEN CFN1$ FOR BINARY AS #2 L = LOF(1) FOR I = 1 TO L GET #1, I, A$ H% = ASC(A$) AC% = H% + CD%: IF AC% > 255 THEN AC% = AC% - 256 將ASCII值和密碼餘數值相加,若大於255則減去256 IF AC% >= 249 THEN 260 '超過249則商大於10,無法存個位數 A% = INT((AC%) / 25) '計算商 C% = AC% - A% * 25 '計算餘數 IF C% = 7 OR C% = 18 THEN LOCATE 15, 30: PRINT "Proceeding : "; I '顯示進行加密的進度 END IF AC% = C% * 10 + A% '以餘數當十位數,以商當個位數,計算新數值 260 PUT #2, I, AC% '將演算結果存進加密檔 NEXT I LOCATE 15, 30 BEEP: LOCATE 20, 20: INPUT ; "Hit RETURN to continue.", ANS2$: GOTO 50 這一段是解密常式,將加密演算法反向操作,把ASCII數值還原,再存入解密檔 370 CLS : BEEP: LOCATE 7, 20: PRINT "Charade file -> ASCII (Binary) file" LOCATE 9, 20: INPUT "Charade file name "; CFN2$: IF CFN2$ = "" THEN 370 LOCATE 11, 20: INPUT "Target file name "; TFN2$: IF TFN2$ = "" THEN 370 GOSUB 600 OPEN CFN2$ FOR BINARY AS #1 OPEN TFN2$ FOR BINARY AS #2 L = LOF(1) - 1 FOR I = 1 TO L GET #1, I, A$ AC% = ASC(A$) IF AC% >= 249 THEN 500 C% = INT(AC% / 10): D% = AC% - C% * 10 'C% 為十位數, D%為個位數 AC% = D% * 25 + C% 'D%為原來的商,C%為原來的餘數 IF D% = 2 OR D% = 7 THEN LOCATE 15, 30: PRINT "Proceeding : "; I 500 H% = AC% - CD%: IF H% < 0 THEN H% = H% + 256 B$ = CHR$(H%) PUT #2, I, B$ NEXT I LOCATE 15, 30: PRINT "Proceeding : "; I 顯示進行解密的進度 BEEP: LOCATE 20, 20: INPUT ; "Hit RETURN to continue.", ANS2$: GOTO 50 END SUB 600 用以計算密碼的餘數值,由於ASCII值為0-255,故除以256再取餘數值, 密碼設計為五位數只是障眼法,目的是取一個隨機的ASCII值來運算 600 BEEP: LOCATE 13, 20: PRINT "Code Number (XXXXX) : ": CD$ = INPUT$(5) CD& = VAL(CD$): IF CD& > 99999 OR CD& < 1 THEN PLAY ECG$: GOTO 600 CD% = CD& - (INT(CD& / 256)) * 256 RETURN 這種加密方式由於一次處理一個BYTE,速度較慢,而且密碼為定值,被解開的機率較大。
50 CLS : A6$ = CHR$(110): A12$ = CHR$(111): A15$ = CHR$(121): A16$ = CHR$(84) LOCATE 1, 1 PRINT "CHarades 2.0 Copyright " + A16$ + A12$ + A6$ + A15$ + " Lab 1992" IF A16$ <> "T" OR A6$ <> "n" OR A12$ <> "o" OR A15$ <> "y" THEN 50 CLEAR : DIM M$(4): ECG$ = "MF L16O2ECG>CEG>CL32O2CDEFGAB>CDEFGAB>C" M$(1) = " 1: Charades " M$(2) = " 2: Reduction " M$(3) = " 3: Exit to DOS " FOR Y = 1 TO 3: LOCATE 2 * Y + 6, 30: PRINT M$(Y): NEXT Y LOCATE , , 0 Y = 1: MVE = NO: X = 1: Q$ = "" WHILE Q$ <> CHR$(13) LOCATE 2 * Y + 6, 30: COLOR 14, 4: PRINT M$(Y): COLOR 15, 1 Q$ = INKEY$: WHILE Q$ = "": Q$ = INKEY$: WEND IF LEN(Q$) = 2 AND ASC(RIGHT$(Q$, 1)) = 72 THEN MVE = YES: X = Y - 1: IF X = 0 THEN X = 3 END IF END IF IF LEN(Q$) = 2 AND ASC(RIGHT$(Q$, 1)) = 80 THEN MVE = YES: X = Y + 1: IF X = 4 THEN X = 1 END IF END IF 'Call DOS shell IF ASC(RIGHT$(Q$, 1)) = 27 THEN CLS : DEF SEG = &H30: H4E% = PEEK(&H4E): POKE &H4E, 5: SHELL DEF SEG = &H30: POKE &H4E, END IF IF Q$ >= "1" AND Q$ <= "3" THEN X = VAL(Q$): MVE = YES IF Q$ >= "1" AND Q$ <= "3" THEN X = VAL(Q$): MVE = YES IF Q$ >= "1" AND Q$ <= "3" THEN X = VAL(Q$): MVE = YES IF MVE = YES THEN LOCATE 2 * Y + 6, 30: PRINT M$(Y): Y = X: MVE = NO WEND IF Y = 1 THEN 110 IF Y = 2 THEN 370 IF Y = 3 THEN PLAY ECG$: CLS : END 以上程式說明,請參考規則式加密法部份 加密常式: 輸入相關檔名,打開檔案,視檔案相對長度決定一次讀入字串和陣列大小 110 CLS LOCATE 7, 20: PRINT "Input file name for Charades Process" LOCATE 9, 20: INPUT "Source file: ", SFN1$: IF SFN1$ = "" THEN 110 LOCATE 11, 20: INPUT "Signature file: ", CFN1$: IF CFN1$ = "" THEN 110 LOCATE 13, 20: INPUT "Charades file: ", TFN1$: IF TFN1$ = "" THEN 110 OPEN SFN1$ FOR BINARY AS #1 OPEN CFN1$ FOR BINARY AS #2 OPEN TFN1$ FOR BINARY AS #3 L1 = LOF(1) L2 = LOF(2) 若檔名輸入有誤,則重新輸入 IF L1=0 OR L2=0 THEN BEEP: LOCATE 20,20 INPUT ; "File Error! Hit RETURN to continue.", ANS2$ GOTO 110 END IF IF L1 > L2 THEN IL = L2 ELSE IL = L1 以來源檔及簽名檔中較小的檔案長度作為字串陣列設定值IL IF IL > 20480 THEN IL = 20480 'IL最大值為20K BYTE 設定動態定長字串陣列 '$DYNAMIC DIM RD$(2) 定義字串變數長度 RD$(1) = SPACE$(IL) RD$(2) = SPACE$(IL) 若來源檔大於一次處理長度則分段進行加密,否則一次完成 IF L1 > IL THEN GOSUB RECHA ELSE GOSUB NONRECHA ERASE RD$ '將動態陣列移除 CLOSE : BEEP: LOCATE 20, 20: INPUT ; "Hit RETURN to continue.", ANS2$: GOTO 50 一次完成加密常式 NONRECHA: GET #1, , RD$(1) GET #2, , RD$(2) FOR I = 1 TO IL DSOR$ = MID$(RD$(1), I, 1) DCHA$ = MID$(RD$(2), I, 1) SOR% = ASC(DSOR$) CHA% = ASC(DCHA$) TAG% = SOR% + CHA%: IF TAG% > 255 THEN TAG% = TAG% - 256 必要時可在此處加上其他演算法變碼 DSOR$ = CHR$(TAG%) PUT #3, , DSOR$ NEXT I RETURN 分次完成加密常式 RECHA: LAST = 0 JT = INT(L1 / IL) + 1 FOR J = 1 TO JT GET #1, , RD$(1) GET #2, 1, RD$(2) FOR I = 1 TO IL DSOR$ = MID$(RD$(1), I, 1) DCHA$ = MID$(RD$(2), I, 1) SOR% = ASC(DSOR$) CHA% = ASC(DCHA$) TAG% = SOR% + CHA%: IF TAG% > 255 THEN TAG% = TAG% - 256 必要時可在此處加上其他演算法變碼 LAST = IL * (J - 1) + I DSOR$ = CHR$(TAG%) PUT #3, LAST, DSOR$ IF LAST = L1 THEN EXIT FOR NEXT I LOCATE 15, 30: PRINT "Proceeding : "; LAST NEXT J RETURN 解密常式: 輸入相關檔名,打開檔案,視檔案相對長度決定一次讀入字串和陣列大小 370 CLS LOCATE 7, 20: PRINT "Input file name for Reduction Process" LOCATE 9, 20: INPUT "Charades file: ", SFN1$: IF SFN1$ = "" THEN 370 LOCATE 11, 20: INPUT "Signature file: ", CFN1$: IF CFN1$ = "" THEN 370 LOCATE 13, 20: INPUT "Reduction file: ", TFN1$: IF TFN1$ = "" THEN 370 OPEN SFN1$ FOR BINARY AS #1 OPEN CFN1$ FOR BINARY AS #2 OPEN TFN1$ FOR BINARY AS #3 L1 = LOF(1) L2 = LOF(2) 若檔名輸入有誤,則重新輸入 IF L1=0 OR L2=0 THEN BEEP: LOCATE 20,20 INPUT ; "File Error! Hit RETURN to continue.", ANS2$ GOTO 370 END IF IF L1 > L2 THEN IL = L2 ELSE IL = L1 IF IL > 20480 THEN IL = 20480 DIM RD$(2) RD$(1) = SPACE$(IL) RD$(2) = SPACE$(IL) IF L1 > IL THEN GOSUB REDUC ELSE GOSUB NONREDUC CLOSE : BEEP: LOCATE 20, 20: INPUT ; "Hit RETURN to continue.", ANS2$: GOTO 50 一次完成解密常式 NONREDUC: GET #1, , RD$(1) GET #2, , RD$(2) FOR I = 1 TO IL DSOR$ = MID$(RD$(1), I, 1) DCHA$ = MID$(RD$(2), I, 1) SOR% = ASC(DSOR$) CHA% = ASC(DCHA$) TAG% = SOR% - CHA%: IF TAG% < 0 THEN TAG% = TAG% + 256 DSOR$ = CHR$(TAG%) PUT #3, , DSOR$ NEXT I RETURN 分次完成解密常式 REDUC: LAST = 0 JT = INT(L1 / IL) + 1 FOR J = 1 TO JT GET #1, , RD$(1) GET #2, 1, RD$(2) FOR I = 1 TO IL DSOR$ = MID$(RD$(1), I, 1) DCHA$ = MID$(RD$(2), I, 1) SOR% = ASC(DSOR$) CHA% = ASC(DCHA$) TAG% = SOR% - CHA%: IF TAG% < 0 THEN TAG% = TAG% + 256 LAST = IL * (J - 1) + I DSOR$ = CHR$(TAG%) PUT #3, LAST, DSOR$ IF LAST = L1 THEN EXIT FOR NEXT I LOCATE 15, 30: PRINT "Proceeding : "; LAST NEXT J RETURN
This website is sponsored
by VIKON Corp.
Copyright July 1996.
All rights reserved.
Last update : 10-20-99
有什麼建議嗎 ? 來信請寄:
vikontony@gmail.com