QB / QB64 Discussion Forum     RULES     Other Subforums, Links and Downloads    Index of Threads

 


  << Previous Topic | Next Topic >>Return to Index  

ProgramList Mac

January 22 2002 at 6:44 PM
Mac  (Premier Login iorr5t)
Owner

 
The first program I ever wrote was for the NORC
http://www.columbia.edu/acis/history/norc-herald.html

I had no access to the 2 million dollar computer, so I don't know if my programs had bugs or not. I learned from a book and was excited about computer power.

At the University of Texas in 1958, I wrote some programs as part of a numerical analysis mathematics course on the IBM 650.
http://www.columbia.edu/acis/history/650.html

The machine had no firmware, so one had to manually enter the first instructions through the console. These instructions were the bootstrap that then loaded the software, which was a card deck.

At the time, the general consensus was that, with the invention of a language scientists and numerical analysts could use, FORTRAN, there was no further need for programmers!

I then joined IBM in 1958 as a programmer and was trained on the SAC/SAGE computer
http://www.mitre.org/about/sage.html
to write "maintenance programs". It seems that the zillions of electronic tubes used could fail, so as I had a background in Electrical Engineering, I was to write programs to vary the plate voltage (we had an instruction for that!) of a given index register or other live register and see if it was "about to fail". If so, I swapped to the alternate tube and popped the failing tube out and lit a light on the computer so the engineers could remove it and supply a new one.

Well, I later got into assembly programming and, as they say, "the rest is history".

One item: the first "Program I am proud of" was a little one-card program for the IBM-709 called "Busy Bee". You see, we programmers had to come in during the middle of the night at IBM and debug on test computers almost ready for shipment to a customer. But sometimes we had to leave the computer for a snack or to rest or redesign our programs and while we were away, the engineers would see the computer was idle and do power off. That was a big deal in those days. It took a LONG time to power up again. So my program would blink the lights at random and it appeared to be working on some complex problem. All the programmers had a Busy Bee card in their possession when in the lab.

My first personal computer was the Commodore VIC-20
http://www.old-computers.com/museum/computer.asp?c=252

It was connected to your TV and had a display of about 10 lines, 40 characters wide. It was mainly for games, and I wrote many programs, such as
An Algebra Drill: Solve 2 equations in 2 unknowns
BINGO
which I later converted to BASICA. These are published (see replies)

I actually wrote a program to connect to the IBM mainframe we were using at the office and demonstrated to management that microcomputers would be an excellent interface to the mainframe. This was ignored and the company eventually was forced out of the business when microcomputers became popular.

I used the VIC-20 for 5 years and still have it in storage with many cassette tapes. But finally I gave in a bought the next home computer: the DOS-based IBM 286
http://www.old-computers.com/museum/computer.asp?st=1&c=260

This I used for many years. It was perfect and did everything I wanted. But it had no mouse and when the Internet became usable, I finally got my current system: DELL 500 Mhz with WindowsNT.

As you can guess, I have programmed in machine language, COBOL, FORTRAN, PL/I and you name it. But I am still fascinated with DOS/QBasic.

Mac


    
This message has been edited by iorr5t on May 18, 2007 1:52 PM


 
 Respond to this message   
AuthorReply
Mac
(Premier Login iorr5t)
Owner

SuperC: An encryption/decryption program

January 26 2002, 2:58 PM 

DECLARE SUB CSub.Pause (Msg AS STRING)
DECLARE SUB CSub.GetKeyI (strKeyI AS STRING, fleKeyV AS STRING)
DECLARE SUB CSub.GenKey (strKeyE AS STRING)
DECLARE SUB CSub.Kernal (intS AS INTEGER, lngKernal AS LONG, strKey AS STRING)
DECLARE SUB CSub.Convert (strCMD AS STRING, lngKernal AS LONG, strF1 AS STRING, strF2 AS STRING)
DECLARE SUB CSub.Markup (strCMD AS STRING, lngKernal AS LONG, strF1 AS STRING)
DECLARE SUB CSub.IO (strCMD AS STRING, strKeyE AS STRING, strF1 AS STRING, strF2 AS STRING)
DECLARE SUB CSub.Zap (strF1 AS STRING)
DIM strKeyI AS STRING: 'Internal Key
DIM strKeyE AS STRING: 'External Key
DIM fleTest AS STRING
DIM fleOK AS INTEGER
GOTO Main

REM SuperC.bas - - - - - Super-Crypto with Crypto-Nite
REM * ** *** An Encryption/Decryption Machine *** ** *
REM Permission granted for personal use of this to keep diaries, etc.
REM Components may not be copied to other programs.
REM Instructions:
REM File to be Encrypted: Plain.txt
REM File to be Decrypted: Crypto.txt
REM When prompted, enter a key you make up.
REM Sample Key: J3mm29
REM Sample Key: My dog has fleez and has to sneeze
REM Sample Key: On November 11 I downloaded this great machine

TestFile:
ON ERROR GOTO L331
OPEN fleTest FOR INPUT AS #1
ON ERROR GOTO 0
fleOK = 1
CLOSE
RETURN
L331:
RESUME L332
L332:
ON ERROR GOTO 0
fleOK = 0
RETURN

Main:
' Step 1: Find out if there is something to do
fleTest = "Plain.txt": GOSUB TestFile
Plain% = fleOK
fleTest = "Crypto.txt": GOSUB TestFile
Crypto% = fleOK
SELECT CASE (2 * Plain%) + Crypto%
CASE 0:
  CSub.Pause "There is nothing to do. Create Plain.txt or Crypto.txt"
  SYSTEM
CASE 3:
  CSub.Pause "You need to get rid of Plain.txt or Crypto.txt": SYSTEM
END SELECT

' Step 2: Get the Internal Key
fleTest = "SuperC.dat": GOSUB TestFile
IF fleOK = 0 THEN
   OPEN fleTest FOR OUTPUT AS #1
   PRINT #1, "Key Verification File"
   CLOSE
END IF
CSub.GetKeyI strKeyI, fleTest
IF strKeyI = "" THEN CSub.Pause "Terminating Run": SYSTEM

' Step 3: Encrypt or Decrypt the Message
IF Plain% = 1 THEN GOTO Encrypt ELSE GOTO Decrypt

REM                      E N C R Y P T I O N
Encrypt:
PRINT "Encrypting . . ."
CSub.GenKey strKeyE
DIM lngKernal AS LONG
lngKernal = 578433
CSub.Kernal 7, lngKernal, strKeyI + strKeyE
CSub.Convert "Normal to Markup", lngKernal, "Plain.txt", "Markup.txt"
CSub.Markup "Encrypt", lngKernal, "Markup.txt"
CSub.IO "Write", strKeyE, "Markup.txt", "Crypto.txt"
CSub.Zap "Markup.txt"
CSub.Zap "Plain.txt"
SYSTEM

REM                      D E C R Y P T I O N
Decrypt:
PRINT "Decrypting . . ."
CSub.IO "Read", strKeyE, "Crypto.txt", "Markup.txt"
lngKernal = 578433
CSub.Kernal 7, lngKernal, strKeyI + strKeyE
CSub.Markup "Decrypt", lngKernal, "Markup.txt"
CSub.Convert "Markup to Normal", lngKernal, "Markup.txt", "Plain.txt"
CSub.Zap "Markup.txt"
CSub.Zap "Crypto.txt"
SYSTEM

SUB CSub.Convert (strCMD AS STRING, lngKernal AS LONG, strF1 AS STRING, strF2 AS STRING)
REM Copyright 2001 Hilliard McLamore
DIM c$(255): ' Translate to Char
DIM c0$(255): 'Translate to Bin (no prefix)
DIM c1$(255): 'Translate to Bin (prefix 125)
DIM c2$(255): 'Translate to Bin (prefix 126)
DIM V13 AS STRING * 1: V13 = CHR$(13)
DIM V10 AS STRING * 1: V10 = CHR$(10)
DIM V32 AS STRING * 1: V32 = " "
DIM ndxM AS LONG: ' Markup Index
DIM ndxN AS LONG: ' Normal Index
DIM chrM AS STRING * 1: ' Markup Character
DIM chrN AS STRING * 1: ' Normal Character

SELECT CASE strCMD
CASE "Normal to Markup"
  GOSUB Init.Tables
  Normal$ = strF1
  Markup$ = strF2
  GOSUB Normal.to.Markup
CASE "Markup to Normal"
  GOSUB Init.Tables
  Markup$ = strF1
  Normal$ = strF2
  GOSUB Markup.to.Normal
CASE ELSE: STOP
END SELECT
EXIT SUB

Markup.to.Normal:
OPEN Markup$ FOR BINARY AS #1
OPEN Normal$ FOR OUTPUT AS #2: CLOSE #2: ' Ensure zero size
OPEN Normal$ FOR BINARY AS #2
ndxN = 1
lngS = LOF(1)
GOSUB Compute.lngO
z% = 1
FOR ndxM = lngO TO LOF(1): GOSUB DoMarkup: NEXT ndxM
FOR ndxM = z% TO lngO - 1: GOSUB DoMarkup: NEXT ndxM
CLOSE
RETURN

DoMarkup:
GET #1, ndxM, chrM
SELECT CASE chrM
CASE CHR$(123):
  PUT #2, ndxN, V13: ndxN = ndxN + 1
  PUT #2, ndxN, V10: ndxN = ndxN + 1
CASE CHR$(124):
  PUT #2, ndxN, V32: ndxN = ndxN + 1
CASE CHR$(125):
  IF ndxM < lngS THEN
    ndxM = ndxM + 1
    GET #1, ndxM, chrM
  ELSE
    GET #1, 1, chrM: z% = 2
  END IF
  PUT #2, ndxN, c1$(ASC(chrM)): ndxN = ndxN + 1
CASE CHR$(126):
  IF ndxM < lngS THEN
    ndxM = ndxM + 1
    GET #1, ndxM, chrM
  ELSE
    GET #1, 1, chrM: z% = 2
  END IF
  PUT #2, ndxN, c2$(ASC(chrM)): ndxN = ndxN + 1
CASE ELSE:
  PUT #2, ndxN, chrM: ndxN = ndxN + 1
END SELECT
RETURN

Normal.to.Markup:
OPEN Markup$ FOR OUTPUT AS #2: CLOSE #2:  'Ensure size zero
OPEN Normal$ FOR BINARY AS #1
lngS = 0: lngO = 0
GOSUB DoPass: 'Compute lngS
OPEN Markup$ FOR BINARY AS #2
GOSUB Compute.lngO
ndxM = lngO - 1
GOSUB DoPass: 'BuildFile
CLOSE
RETURN

Compute.lngO:
w# = RND(-13 - lngKernal)
w# = 0: FOR i = 1 TO 10: w# = w# + (RND(1) * 173): NEXT i
w# = RND(-13 - w# * 55773)
lngO = INT((RND(1) * lngS)) + 1
IF lngO > lngS THEN lngO = 1
IF zzzO > 0 THEN lngO = zzzO
RETURN

DoPass:
DIM strL AS STRING: ' Just a work string
FOR ndxN = 1 TO LOF(1)
  GET #1, ndxN, chrN
  IF ASC(chrN) = 13 THEN
    DIM chrNt AS STRING * 1
    GET #1, ndxN + 1, chrNt
    IF ASC(chrNt) = 10 THEN
      strL = strL + CHR$(123)
      ndxN = ndxN + 1
    ELSE
      strL = strL + c$(ASC(chrN))
    END IF
  ELSE
    strL = strL + c$(ASC(chrN))
  END IF
  IF LEN(strL) > 79 THEN GOSUB WritestrL
NEXT ndxN
IF LEN(strL) > 0 THEN GOSUB WritestrL
RETURN

WritestrL:
IF lngO = 0 THEN lngS = lngS + LEN(strL): strL = "": RETURN
FOR ll = 1 TO LEN(strL)
  LSET chrM = MID$(strL, ll, 1)
  ndxM = ndxM + 1: IF ndxM > lngS THEN ndxM = 1
  PUT #2, ndxM, chrM
NEXT ll
strL = ""
RETURN

Init.Tables:
FOR i = 33 TO 122
  c$(i) = CHR$(i)
  c0$(i) = CHR$(i)
NEXT i
'
k = 32
FOR i = 0 TO 31
  k = k + 1
  c$(i) = CHR$(125) + CHR$(k)
  c1$(k) = CHR$(i)
NEXT i
FOR i = 123 TO 180
  k = k + 1
  c$(i) = CHR$(125) + CHR$(k)
  c1$(k) = CHR$(i)
NEXT i
'
k = 32
FOR i = 181 TO 255
  k = k + 1
  c$(i) = CHR$(126) + CHR$(k)
  c2$(k) = CHR$(i)
NEXT i
'
c$(32) = CHR$(124)
RETURN
'
END SUB

SUB CSub.GenKey (strK AS STRING)
DIM intM AS INTEGER
RANDOMIZE TIMER
w$ = DATE$ + TIME$
FOR i = 1 TO LEN(w$)
  c% = INT(94 * RND(1))
  intM = ASC(MID$(w$, i, 1))
  intM = intM + c%: IF intM > 126 THEN intM = intM - 94
  MID$(w$, i, 1) = CHR$(intM)
NEXT i
strK = w$
END SUB

SUB CSub.GetKeyI (strKeyI AS STRING, fleKeyV AS STRING)
CLS
LOCATE 3, 35: PRINT "Crypto-Nite Version 1.3"
LOCATE 7, 1
PRINT "Enter your Key, or hit Enter to terminate run.": PRINT
INPUT "Key: ", strKeyI
IF strKeyI = "" THEN EXIT SUB
DIM strV AS STRING: ' A 3-digit verifier to detect typo errors
GOSUB GetV
OPEN fleKeyV FOR INPUT AS #1: LINE INPUT #1, l$
DO WHILE NOT EOF(1)
  LINE INPUT #1, l$
  IF LEFT$(l$, 3) = strV THEN strV = ""
LOOP
CLOSE
IF strV = "" THEN EXIT SUB
PRINT "I haven't seen this key before. What do you want me to do?"
PRINT "  1 - Accept this as a new key"
PRINT "  2 - Terminate run and start over"
DO: k$ = INKEY$: LOOP WHILE ((k$ <> "1") AND (k$ <> "2"))
IF k$ = "2" THEN strKeyI = " ": EXIT SUB
OPEN fleKeyV FOR APPEND AS #1
PRINT #1, strV; " created on "; DATE$; " at "; TIME$
CLOSE
EXIT SUB

GetV:
w$ = strKeyI + CHR$(13)
DIM y AS INTEGER
y = RND(-577823)
DIM e1 AS DOUBLE, e2 AS DOUBLE, e3 AS DOUBLE
DIM i, j
DO
FOR i = 1 TO 100
j = j + 1: IF j > LEN(w$) THEN j = 1
e1 = e1 + (RND(1) * ASC(MID$(w$, j, 1)))
e2 = e2 + (RND(1) * ASC(MID$(w$, j, 1)))
NEXT i
e1 = 1 + e1 - INT(e1)
e2 = 1 + e2 - INT(e2)
e3 = e1 * e2
WHILE e3 > 1: e3 = e3 - RND(1): WEND
w$ = STR$(e3)
LOOP WHILE LEN(w$) < 17
strV = MID$(w$, 10, 3)
RETURN
END SUB

SUB CSub.IO (strCMD AS STRING, strKeyE AS STRING, strF1 AS STRING, strF2 AS STRING)
DIM fleB AS STRING: 'Binary File
DIM ndxB AS LONG: ' Index for Binary file
DIM chrB AS STRING * 1: ' Character of Binary file
DIM fleQ AS STRING: 'Sequential file
DIM strQ AS STRING: ' Line in sequential file

SELECT CASE strCMD
CASE "Write": GOSUB IOWrite
CASE "Read": GOSUB IORead
END SELECT
CLOSE
EXIT SUB

IOWrite:
fleQ = strF2
fleB = strF1
OPEN fleQ FOR OUTPUT AS #1
PRINT #1, strKeyE
strQ = ""
OPEN fleB FOR BINARY AS #2
FOR ndxB = 1 TO LOF(2)
GET #2, ndxB, chrB
IF chrB = "&" THEN strQ = strQ + CHR$(127) ELSE strQ = strQ + chrB
' Output strings are 80-characters, suitable for transmission
IF LEN(strQ) > 79 THEN PRINT #1, strQ: strQ = ""
NEXT ndxB
IF LEN(strQ) > 0 THEN PRINT #1, strQ
RETURN

IORead:
fleQ = strF1
fleB = strF2
OPEN fleQ FOR INPUT AS #1
LINE INPUT #1, strKeyE
OPEN fleB FOR BINARY AS #2
ndxB = 0
DO WHILE NOT EOF(1)
LINE INPUT #1, strQ
FOR i = 1 TO LEN(strQ)
LSET chrB = MID$(strQ, i, 1)
IF chrB = CHR$(127) THEN LSET chrB = "&"
ndxB = ndxB + 1
PUT #2, ndxB, chrB
NEXT i
LOOP
RETURN

END SUB

SUB CSub.Kernal (intS AS INTEGER, lngKernal AS LONG, strKey AS STRING)
REM Copyright 2001 Hilliard McLamore
DIM strW AS STRING
WHILE LEN(strW) < 100: strW = strW + strKey: WEND
DIM c%(100)
FOR i = 1 TO 100: c%(i) = ASC(MID$(strW, i, 1)): NEXT i
FOR secur.cnt = 1 TO intS: GOSUB Scramble: NEXT secur.cnt
EXIT SUB
Scramble:
y# = RND(-13 - lngKernal)
FOR SwapI = 1 TO 100: SWAP c%(1 + INT(RND(1) * 100)), c%(1 + INT(RND(1) * 100)): NEXT SwapI
DIM dblW AS DOUBLE
dblW = 0
FOR i = 1 TO 100: dblW = dblW + (c%(i) * RND(1)): NEXT i
lngKernal = (dblW - INT(dblW)) * 2147483647
RETURN
END SUB

SUB CSub.Markup (strCMD AS STRING, lngKernal AS LONG, strF1 AS STRING)
REM Copyright 2001 Hilliard McLamore
y# = RND(-13 - lngKernal)
OPEN strF1 FOR BINARY AS #1
DIM chrM AS STRING * 1
DIM ndxM AS LONG
DIM intM AS INTEGER
FOR ndxM = 1 TO LOF(1)
  GET #1, ndxM, chrM
  intM = ASC(chrM)
  c% = INT(94 * RND(1))
  SELECT CASE strCMD
  CASE "Encrypt": intM = intM + c%: IF intM > 126 THEN intM = intM - 94
  CASE "Decrypt": intM = intM - c%: IF intM < 33 THEN intM = intM + 94
  END SELECT
  LSET chrM = CHR$(intM)
  PUT #1, ndxM, chrM
NEXT ndxM
CLOSE
END SUB

SUB CSub.Pause (Msg AS STRING)
PRINT : PRINT Msg: PRINT
PRINT "---Press any key to continue"
SLEEP
END SUB

SUB CSub.Zap (strF1 AS STRING)
OPEN strF1 FOR BINARY AS #1
DIM ndx1 AS LONG
DIM chr1 AS STRING
chr1 = "Q"
FOR ndx1 = 1 TO LOF(1): PUT #1, ndx1, chr1: NEXT ndx1
CLOSE
KILL strF1
END SUB


    
This message has been edited by iorr5t on May 5, 2006 5:57 AM


 
 Respond to this message   
Mac
(Premier Login iorr5t)
Owner

Explanation

January 26 2002, 4:30 PM 

In the directory you call SuperC from, you will have one of the following files:
„h Plain.txt
„h Crypto.txt

If you have Plain.txt, the program will erase it in such a manner as to make it completely unrecoverable. This is so any Enemy who gets access to your computer cannot find it. The program will produce Crypto.txt which is suitable to be transmitted to anyone who has a copy of Crypto.bas and who knows your Key.

If you have Crypto.txt, the reverse is done. It is your responsibility to take care of Plain.txt. Crypto.txt is erased so that there is no copy of both available to whoever might want to figure out your Key.

If you examine Crypto.bas, you will find a two lines that start: "CSub.Kernal 7". The seven is a security level. The higher you make it, the harder for someone to discover your key by trail and error. Seven is quite high and is fast. I tried 500 and the delay was about 15 seconds before starting encryption or decryption. The security of an individual message is not affected ¡V It is already hopelessly difficult to decrypt. This just keeps someone from trying all possible keys. The level of 7 would mean a reasonable powerful home PC would take a few weeks to break your key. The level 500 means a few trillion years. A supercomputer might do it in a few weeks.

To further make life miserable for a cryptographer, the text is folded before encryption. This is so the cryptographer doesn't know that the last character is a chr$(13) or whatever normally ends txt files.

If you encrypt a message using a given Key, and then encrypt the same message again, you will notice the cryptograms are not similar. This is part of the security. However, either one will decrypt successfully.

A short key, such as "MyKey" could be guessed at security level 7 in a few hours (by a trained cryptographer who wrote a C++ program to emulate the decryption process.) So use something longer such as "Fat dogs eat too much". This will take weeks even at level 7.

The security afforded by this program is far more than needed by any normal person, but was provided as an intellectual exercise. I omitted one piece of code that would make encryption impossible without the key. This is to give the CIA a chance in case bad people get hold of the logic. But don't worry, I guarantee nobody will decrypt the messages you may want to send to your friends using this program.

By the way, there is another feature. A file, SuperC.dat, is kept with entries such as
Key Verification File
935 created on 11-04-2001 at 19:45:43

This is just to protect you from errors. The file is not required and can be safely deleted. The entries correspond to keys you have chosen. You can delete entries also.

Let's say you have a friend who has a copy of Crypto.bas and you have agreed on the password "My house is near the park." Now you want to send a message and you enter the password, but forget to capitalize the "M". The program will recognize this as a new password and warn you. Great! Otherwise, you would have sent a message your friend cannot decrypt.

 
 Respond to this message   
codeworm
(no login)

Key is "My Key" (6 chars, two caps)

February 12 2002, 11:26 AM 

X{<Ux*(g85L0hU-Q=R
^c.8CXOsbK)x0Y0S,b!GvNrx5|9y~lKSGeo,!k$Q)EUdBkjj_De+#G2bz0>!\(S{PSR^s)O0X2ZOA\RL
ZwJ<hg%1eYy\G0l]kLZ)4?Imcerj\LW/=N.!/yV7TFcvaTvEt"^JN?vn6I[9yhw[E1n8YPana-ja({^H
GIK[.~eL3r%8_>Q5+[~j`K/~UIheDnZ-p&Y#e'v}sL-qU,`I0iA(dEVxYTP0<:lRaGp0e[~9pbIcTYZ|
1vI;`9`M5X:]HR}ye6MU~=6Fo#`0Y5-w&Py[00Duu+S;.UzzomcX*6x_1XNqv!:O]#''/=!-"}D*21;5
xW?Q?h}bZq*!N}G`Oi_3%c3Zn*Qaiqww}emceO)_uN1sCV*gVT9IN8pdE}'#Ku|Pd7a(0JL1?48)>.5C
9A2ee|6:nu:7shJnyRw?'2Pg^A~mh#4oz"\}

 
 Respond to this message   
codeworm
(no login)

Arrgh, goofed. Delete this one. (nt)*

February 12 2002, 11:29 AM 

sdf

 
 Respond to this message   
codeworm
(no login)

Key is "My key" (6 chars, one cap)

February 12 2002, 11:28 AM 

X{<Ux*(g85L0hU-Q=R
^c.8CXOsbK)x0Y0S,b!GvNrx5|9y~lKSGeo,!k$Q)EUdBkjj_De+#G2bz0>!\(S{PSR^s)O0X2ZOA\RL
ZwJ<hg%1eYy\G0l]kLZ)4?Imcerj\LW/=N.!/yV7TFcvaTvEt"^JN?vn6I[9yhw[E1n8YPana-ja({^H
GIK[.~eL3r%8_>Q5+[~j`K/~UIheDnZ-p&Y#e'v}sL-qU,`I0iA(dEVxYTP0<:lRaGp0e[~9pbIcTYZ|
1vI;`9`M5X:]HR}ye6MU~=6Fo#`0Y5-w&Py[00Duu+S;.UzzomcX*6x_1XNqv!:O]#''/=!-"}D*21;5
xW?Q?h}bZq*!N}G`Oi_3%c3Zn*Qaiqww}emceO)_uN1sCV*gVT9IN8pdE}'#Ku|Pd7a(0JL1?48)>.5C
9A2ee|6:nu:7shJnyRw?'2Pg^A~mh#4oz"\}

 
 Respond to this message   
codeworm
(no login)

Possible use of SuperC to post EXE-files?

March 13 2002, 11:27 AM 

I made a copy of QBASIC.EXE and renamed it to Plain.txt

I then encrypted using qbasic /run SuperC
- The input file, Plain.txt, was size 254,799
- It took about 40 seconds
- The output file, Crypto.txt, was size 440,032
- (Plain.txt was deleted, per specification)

I then decrypted, thereby creating a new Plain.txt
- All statistics were the same

I renamed this to x.exe and tried it out. Worked fine!

I compared x.exe to QBASIC.EXE
- I executed the DOS command COMP and got the results "Files compare OK".

I then tried a Word document, an Excell spreadsheet, and a PowerPoint presentation.

Well, Mac, you certainly "walk the walk" as regards posting only debugged code.

Conclusion:

SuperC can be used to encrypt and decrypt programs as well as plain text messages.

This means that if you have a program of some reasonable size that you do not know how to transfer, you can encrypt it and post on the forum.

Actually, that is a bad idea. Maybe whoever has this need can create a forum (it's free - see www.network54.com) then post the cryptogram there then post the URL on our forum. That way people who want to view all messages do not get many pages of cryptogram lines.

Anyway, just thinking out loud.

 
 Respond to this message   
Mac
(Premier Login iorr5t)
Owner

Security Weakness Uncovered

January 23 2003, 1:29 PM 

This program was written under the misconception that the QBasic RND function worked as follows:
1) The user enters RND(-x) and x is used to create some sort of kernal for randomizing.
2) Thereafter, RND would give a sequence unique to x.

I have since discovered that instead, it works as follows:
1) There is a fixed sequence of random numbers (16,777,216 of them).
2) The user enters RND(-x) and x is used to determine a start point for this fixed sequence
3) Thereafter, RND returns numbers from this sequence, looping to the beginning as required.

This means it is MUCH easier to decrypt messages than I thought.

Before, I thought that the enemy would have to issue RND(-1), -2, -3, ... etc. And then use the resultant sequence of random numbers to try to decrypt the message.

Now it is clear that the enemy only has to issue RANDOMIZE TIMER or any other such as RND(-44331). This will result in a starting point. The enemy then creates an array containing the first n random numbers, where n is the size of the cryptogram. Finally, the enemy tries to decrypt using the array. If it doesn't work, then delete the first number from the array and add a new random number. Sure, it will take a while: worst case it will take nearly 16,777,216 attempts to solve. But each attempt only requires the execution of RND one time.

Shown below is a study of this using a simulated RND function so that instead of 16,777,216 possible numbers, there are only 52. Given in a program to Encrypt and Decrypt. Given also is a HACKER program where they enemy simply goes through the cases. If you try it, you will see that you succeed in decrypting a message fairly easily.

So, an additional security feature is required. I have a nice one in my VB program, NoSee.Spyw.com. If you have a week or so, you can read the ReadMe that explains it – A translation table that is constantly shuffled.

You are also invited to dream up your own way of increasing the security of SuperC.bas.

Mac

=================== Encrypt/Decrypt Program
DECLARE FUNCTION Mrnd! (n!)
'Note: Mrnd is a simulation of the QBasic RND function to show
'      its essential characteristics

GOSUB Init: 'Determines whether we will E=encrypt D=Decrypt Q=quit
IF CMD$ = "Q" THEN CLS : SYSTEM

gosub GetKey: 'Gets the key, KeyNum, for this message in the range 1-52
y = Mrnd(-KeyNum)' Seed the randomizer from the key

GOSUB GetM: 'Get a plaintext/cryptogram, M$, (letters a-z only)

FOR i = 1 TO LEN(m$)
  c$ = MID$(m$, i, 1)
  IF CMD$ = "E" THEN
    c = ASC(c$) + Mrnd(1): IF c > 122 THEN c = c - 26
  ELSE
    c = ASC(c$) - Mrnd(1): IF c < 97 THEN c = c + 26
  END IF
  oo$ = oo$ + CHR$(c)
NEXT i
PRINT oo$
LOCATE 25, 1
PRINT "Press 'C' to continue...";
do: k$=inkey$: loop while ucase$(k$)<>"C"
RUN

SYSTEM

Init:
CLS
LOCATE 10, 10: PRINT "Encrypt/Decrypt/Quit"
LOCATE 11, 15, 1: PRINT "EDQ: ";
DO
  DO: CMD$ = UCASE$(INKEY$): LOOP WHILE CMD$ = ""
LOOP WHILE INSTR("EDQ", CMD$) = 0
IF CMD$ = "Q" THEN RETURN
CLS
LOCATE 10, 35
IF CMD$ = "E" THEN PRINT "Encrypting" ELSE PRINT "Decrypting"
RETURN

GetKey: 'Gets the key, KeyNum, for this message in the range 1-52
LOCATE 15, 1
DO
  INPUT "Enter the key (1-52)"; Key$
  IF Key$ = "" THEN run
  KeyNum = VAL(Key$)
LOOP UNTIL (KeyNum > 0) AND (KeyNum < 53)
RETURN

GetM: 'Get a message, M$, to encrypt (letters a-z only)
DO
  INPUT "lowercasemessagenospaces"; inp$: IF inp$ = "" THEN run
  m$ = LCASE$(inp$)
  IF m$ <> inp$ THEN inp$ = " "
LOOP WHILE INSTR(inp$, " ") > 0
RETURN

FUNCTION Mrnd (n)
CONST strP = "22044240184449102405121915113316020828322014293826274101063903502543234630131707483751094734363552213145"
CONST strR = "02082123071316111221152216020818180600012325091424151705110605040903202013031419120010071722040124192510"
STATIC locc
IF n < 0 THEN
  w = -n
  IF w > 52 THEN w = 26
  locc = VAL(MID$(strP, (2 * w) - 1, 2))
ELSE
  locc = locc + 1
  IF locc > 52 THEN locc = 1
END IF
Mrnd = VAL(MID$(strR, (locc * 2) - 1, 2))
END FUNCTION

=================== Hacker Program
DECLARE FUNCTION Mrnd! (n!)
CLS
DO
  INPUT "lowercasemessagenospaces"; inp$: IF inp$ = "" THEN SYSTEM
  m$ = LCASE$(inp$)
  IF m$ <> inp$ THEN inp$ = " "
LOOP WHILE INSTR(inp$, " ") > 0

DIM m%(1000)
ml = LEN(m$)
FOR i = 1 TO ml: m%(i) = Mrnd(1): NEXT i
DO
  GOSUB TestMsg
  FOR i = 1 TO ml - 1: m%(i) = m%(i + 1): NEXT i
  m%(ml) = Mrnd(1)
LOOP
TestMsg:
oo$ = ""
FOR i = 1 TO LEN(m$)
  c$ = MID$(m$, i, 1)
  c = ASC(c$) - m%(i)
  IF c < 97 THEN c = c + 26
  oo$ = oo$ + CHR$(c)
NEXT i
PRINT oo$
DO: k$ = INKEY$: LOOP WHILE k$ = ""
IF k$ = CHR$(27) THEN SYSTEM
RETURN

FUNCTION Mrnd (n)
CONST strP = "22044240184449102405121915113316020828322014293826274101063903502543234630131707483751094734363552213145"
CONST strR = "02082123071316111221152216020818180600012325091424151705110605040903202013031419120010071722040124192510"
STATIC locc
IF n < 0 THEN
  w = -n
  IF w > 52 THEN w = 26
  locc = VAL(MID$(strP, (2 * w) - 1, 2))
ELSE
  locc = locc + 1
  IF locc > 52 THEN locc = 1
END IF
Mrnd = VAL(MID$(strR, (locc * 2) - 1, 2))
END FUNCTION

 
 Respond to this message   
Mac
(Premier Login iorr5t)
Owner

Here is a convincing demonstration of zombie's formula

March 3 2003, 7:11 PM 

CLS
FOR i = 1 TO 5: gosub RND1: next i
PRINT "------"
Seed# = y#(1)
FOR i = 1 TO 5: gosub RND2: next i
SYSTEM

RND1: ' ***** ***** This is the number produced by RND
y#(i) = RND * 16777216
PRINT y#(i)
return

RND2: ' ***** ***** This is the number produced by zombie
PRINT Seed#
Temp# = (16598013# * Seed# + 12820163)
Seed# = Temp# - INT(Temp# / 16777216) * 16777216
return

 
 Respond to this message   
Alipha
(Login Mac36)

More on how RND works (URL*)

February 25 2005, 12:24 PM 

http://www.network54.com/Forum/message?forumid=13959&messageid=1109291268

 
 Respond to this message   
Michael Calkins
(Login MCalkins)
ASM Forum

I've borrowed Galleon's "randomize using"...

February 3 2012, 1:05 AM 

DECLARE SUB qRandomizeUsing (s AS SINGLE)
DECLARE FUNCTION qRnd! ()
DIM SHARED qSeed AS LONG
qSeed = &H50000

SUB qRandomizeUsing (s AS SINGLE)
 ' derived from: QB64 0.942 win32: libqbx.cpp: sub_randomize
' this would be so much simpler with unsigned math

 qSeed = CVL(RIGHT$(MKD$(s), 4))
 qSeed = (((qSeed XOR INT(qSeed / &H10000)) AND &HFFFF&) * &H100)
END SUB

FUNCTION qRnd!
 ' derived from:
 ' http://www.network54.com/Forum/178387/message/1046747461/
 ' this would be so much simpler if overflow could be ignored.

 DIM t AS DOUBLE
 t = qSeed
 t = (&HFD43FD * t + &HC39EC3)
 qSeed = t - INT(t / &H1000000) * &H1000000
 qRnd = qSeed / &H1000000
END FUNCTION


    
This message has been edited by MCalkins on Feb 21, 2013 12:57 AM


 
 Respond to this message   
Michael Calkins
(Login MCalkins)
ASM Forum

Qbasic accepts SINGLE seeds

August 22 2012, 12:39 AM 

According to QBASIC Help, the seed is supposed to be an INTEGER. However, RANDOMIZE actually accepts a SINGLE. I will edit the above post to change the s parameter from LONG to SINGLE.

However, I would recommend LONG unless you actually need fractional seeds, such as what you would get from TIMER.

Regards,
Michael

P.S. Also, I removed a temporary variable.

P.S. QB64 allows the code to be simplified (because of unsigned math, and allowance of overflow):
http://www.qb64.net/forum/index.php?topic=6891.msg70939#msg70939


    
This message has been edited by MCalkins on Aug 22, 2012 12:53 AM


 
 Respond to this message   
Clippy
(Login burger2227)
R

Where does it say that?

August 22 2012, 11:01 PM 

It says any value between -32768 and 32767, but it doesn't say integer.

 
 Respond to this message   
Michael Calkins
(Login MCalkins)
ASM Forum

*by using the % symbol: RANDOMIZE [seed%]. I don't see where it says a range...

August 22 2012, 11:38 PM 


 
 Respond to this message   
Clippy
(Login burger2227)
R

In 1.1 not 4.5

August 23 2012, 7:30 AM 

In fact the range QB1.1 and QB4.5 prints to the screen is wrong anyhow. If it can use TIMER values that range is too low. QB4.5 Help uses:

RANDOMIZE [expression]

This also makes it appear to be optional when it will ask if it is not used.

 
 Respond to this message   
Michael Calkins
(Login MCalkins)
ASM Forum

* As indicated in the QB64 source code, the initial state is 0x50000.

February 21 2013, 12:56 AM 



    
This message has been edited by MCalkins on Feb 21, 2013 1:02 AM


 
 Respond to this message   
Michael Calkins
(Login MCalkins)
ASM Forum

* or by PRINT HEX$(RND(0) * 2 ^ 24)

March 23 2015, 6:18 AM 


 
 Respond to this message   
Michael Calkins
(Login MCalkins)
ASM Forum

* zombie's post (url)

February 19 2013, 10:01 PM 

http://www.network54.com/Forum/178565/message/1046721807/last-1127114956/The+facts+about+the+RND+function

 
 Respond to this message   
Mac
(Premier Login iorr5t)
Owner

On the trail to the solution of the security weakness

May 28 2003, 4:52 PM 

Introduction to RND
------------------

The QBasic/VB function RND consists of the equivalent of the following code:
      qqX# = (16598013# * qqA#) + 12820163
      qqA# = qqX# - ((INT(qqX# / 16777216) * 16777216))
Whenever RND is called, the "next" value of qqA# is computed and the number qqa#/16777216 is returned.

This algorithm produces a series of unique numbers which repeats after 16777216 values have been requested.

If one simply codes PRINT RND in a QBasic program, then the first number returned happens to be 11837123/16777216 or 0.7055475. The next value of qqA is computed using the above code to give 8949370, which is returned as 0.533424, etc.

This series of numbers, although not truly "random" is sufficintly random for games and gives good results in simulations of all kinds. However, every time you run the program, you get the same series: 0.7055475, 0.533424, etc. After games and simulations have been debugged, it is often desireable to start reading from the series at another point.

A reasonably random point to start is generated by the function RANDOMIZE TIMER. This will use the current value of the timer to generate a number in the range 0-16777215 which will be the first qqA#, as opposed to always starting with whatever generates 11837123.

The operand zero, RND(0), simply returns qqA#/16777216 without first computing a new value for qqA#. In other words, it returns the same value that the last RND returned.


Introduction to Encryption/Decryption using RND
-----------------------------------------------

One can specify a specific start point by calling RND with a negative operand, for example RND(-1234). This can be useful in cryptography. One converts a password to a number and supplies that to RND as a negative operand. Thereafter the sequence of numbers returned is used to encrypt a message. To decrypt, simply supply the same password but this time, use the sequence to decrypt. The following is a simple example where only letters a-z are used.
CLS
msg$ = "aaabbbccc"
y = RND(-126823) ' Where 126823 was generated from a password
FOR i = 1 TO LEN(msg$)
  c = ASC(MID$(msg$, i, 1)) - 97
  c = c + INT(RND * 26)
  IF c > 26 THEN c = c - 26
  MID$(msg$, i, 1) = CHR$(97 + c)
NEXT i
PRINT msg$ ' Note that it has been encrypted
y = RND(-126823) ' The same password at a later time gives the same seed
FOR i = 1 TO LEN(msg$)
  c = ASC(MID$(msg$, i, 1)) - 97
  c = c - INT(RND * 26)
  IF c < 0 THEN c = c + 26
  MID$(msg$, i, 1) = CHR$(97 + c)
NEXT i
PRINT msg$ ' Note that it has been decrypted
SYSTEM


Problems with Encrypting using RND
----------------------------------

A person without the password, but knowing the way the message was encrypted, can decrypt it in one of two ways:

1) Try y = RND(-1), RND(-2), ..., RND(-16777215) and examine the result.

2) Generate the whole series of 16777216 numbers starting anywhere and shift the message by one.

Either will work on the average after 16777216/2 tries.

Depending on how efficient the 'examine the result' routine is, this is well within the range of feasibility. Thus an encryption scheme that depends solely on RND is not secure against a determined enemy with a good computer.

Thus it is desirable to have a RND function which does not repeat so soon.


Analysis of CRnd - A new RND function
-------------------------------------

Imagine a random number generator that generates the series a,b,c (it repeats after only 3 numbers). We add another such generator that generates the series f,g (it repeats after only 2 numbers). We now take numbers from the first series, combined with the second series to get
af ag bg bf cf cg ag af bf bg cg cf (starts repeating) af ag bg ....

Note this new series does not repeat until after 3*2*2=12 elements.

That is because 3 and 2 are relatively prime. If we chose 4 and 2 we get
af ag bg bf cf cg dg df  (starts repeating) af ag bg ...
The series repeats after 4*2=8 elements.

So with that information, the CRnd SUB uses the normal Basic generator
      qqX# = (16598013# * qqA#) + 12820163
      qqA# = qqX# - ((INT(qqX# / 16777216) * 16777216))
but modified to return only a prime number of elements by rejecting any value of qqA# which exceeds prime number 16777213 minus 1.

And another generator is also used
      qqY# = (8299005 * qqB) + 6410085
      qqB = qqY# - ((INT(qqY# / 8388608) * 8388608))
but modified to reject numbers which exceed 8388593 minus 1.

By combining the results of these two, one obtains a sequence of numbers which do not repeat for 16777213*8388593*2 elements!

This is totally not needed for games and simulations and for those purposes is overkill and too slow. But for cryptography it is ideal. If an enemy had an algorithm that could break a cryptogram based on ordinary RND usage in, say, the miraculous quick time of 5 seconds, then the same algorithm applied to CRnd SUB values would take 971 days!


An Unnecessary Experiment
-------------------------

Experiments have been run that show the ordinary RND function repeats after 16,777,216 values have been returned.

Just for fun, I started a search for repetition and stopped it after 1,296,218,200 values were returned. There was no repetition, of course. It would have taken a few years before I would get to that point.


Efficiency consideration
------------------------

The RND function is efficient because it is a build-in function. CRnd is a SUB, which has the overhead of saving return information in the stack and restoring it. Thus it is considerably slower than RND.

To help a bit, CRnd operates on an array, returning multiple values for one call. The user would then take numbers from the array until it is exhausted and then call CRnd again.



 
 Respond to this message   
Mac
(Premier Login iorr5t)
Owner

CRnd - A more secure RND function

May 28 2003, 4:57 PM 

DECLARE SUB CRnd (CC() AS INTEGER)
CLS

'The CRdn SUB requires an integer array such as MyRND(100)
'To (re)initialize CRnd, the following values are used
'  MyRND(0)=number between 26 and 255 (The max value for random numbers)
'  MyRND(1-max)=numbers between 0 and 255 used to generate the seed
'CRnd will fill the array with random numbers in the range 0-max value.

'                       #### D E M O ####
TestRange = 200 ' You can play with this to test error messages, etc.
DIM MyRND(TestRange) AS INTEGER
MyRND(0) = 26 + 26 + 10' Sample - sufficient to encrypt a-z A-Z 0-9
' Here it is imagined the user will not encrypt other characters.
' For encrypting files, such as EXEs, the user would use 255, not 62.

'=== Simulate the user entered a password that was coverted by
'=== the crypto program to 100 integers 0-255 in MyRND(100)
FOR i = 1 TO TestRange: MyRND(i) = INT(RND * 256): NEXT i
DO
  LINE INPUT "Enter a value 0-255 to simulate a password: "; v$
  v = VAL(v$): IF v = 0 THEN IF v$ <> "0" THEN v = -1
LOOP WHILE (v < 0) OR (v > 255)
MyRND(3) = v ' Change one character to show its effect on output

'=== Illustrate the first 18 values produced in MyRND(100)
FOR test1 = 1 TO 20
  CALL CRnd(MyRND())
  FOR i = 1 TO 18: PRINT MyRND(i); : NEXT i
  PRINT
NEXT test1
SYSTEM

'                       #### T H E   S U B ####
SUB CRnd (CC() AS INTEGER)
STATIC qqR AS INTEGER ' Populate CC() with numbers in range 0-qqR
STATIC qqA AS DOUBLE 'Seed for generator A
STATIC qqB AS DOUBLE 'Seed for generator B
STATIC Which AS INTEGER '0=(step seed A), 1=(step seed B)
STATIC qqX$ ' Digits from generator A, to be combined with
STATIC qqY$ ' Digits from generator B

STATIC CCMax AS INTEGER ' Size of array CC()
IF (CCMax = 0) OR (CC(0) > 0) THEN GOSUB CRnd.First

FOR i = 1 TO CCMax
  IF Which = 0 THEN
    Which = 1
    DO 'Force prime number max 16777213
      'formula reported by QBasic Forum Member zombie
      qqX# = (16598013# * qqA) + 12820163
      qqA = qqX# - ((INT(qqX# / 16777216) * 16777216))
    LOOP WHILE qqA > 16777212
    qqX$ = RIGHT$(STR$(1000000 + qqA), 4)
    IF qqY$ = "" THEN STOP
    t$ = qqX$ + qqY$
  ELSE
    Which = 0
    DO 'Force prime number max 8388593
      'formula developed by QBasic Forum Member Mac
      qqY# = (8299005 * qqB) + 6410085
      qqB = qqY# - ((INT(qqY# / 8388608) * 8388608))
    LOOP WHILE qqB > 8388592
    qqY$ = RIGHT$(STR$(1000000 + qqB), 4)
    IF qqX$ = "" THEN STOP
    t$ = qqY$ + qqX$
  END IF
  mytemp# = (VAL(t$)) / 1000000000000#
  w$ = ""
  FOR j = 1 TO 7 STEP 2: w$ = w$ + MID$(t$, j, 1): NEXT j
  FOR j = 2 TO 8 STEP 2: w$ = w$ + MID$(t$, j, 1): NEXT j
  y = RND(-VAL(w$)): y = RND
  CC(i) = INT(qqR * RND)
NEXT i
EXIT SUB

CRnd.First:
CCMax = UBOUND(CC)
IF (LBOUND(CC) <> 0) OR CCMax < 80 THEN
  PRINT "Bad range for CRnd input array. Use 0-80 or more"
  STOP: SYSTEM
END IF
qqR = CC(0) + 1: CC(0) = 0: ' Save range of output
IF (qqR < 27) OR (qqR > 256) THEN
  PRINT "The zero entry in the input array to CRnd is incorrect!"
  PRINT "On first call, this must contain 26-255"
  PRINT "This number specified the range of values to be returned"
  STOP: SYSTEM
END IF
m1# = 0: m2# = 0 ' Collect two numbers as function of CC(100)
FOR i = 1 TO (CCMax - 1) STEP 2
  r1 = CC(i): IF (r1 > 255) OR (r1 < 0) THEN GOTO Adios
  r2 = CC(i + 1): IF (r2 > 255) OR (r2 < 0) THEN GOTO Adios
  y = RND(-((256 * r1) + r2))
  m1# = m1# + RND + RND
  m2# = m2# + RND + RND
NEXT i
m1# = m1# - INT(m1#)
m2# = m2# - INT(m2#)
y = RND(-(m1# * 345647)): y = RND: qqA = INT(RND * 16777214)
y = RND(-(m2# * 234547)): y = RND: qqB = INT(RND * 8388593)
qqY$ = "": FOR i = 1 TO 6: qqY$ = qqY$ + RIGHT$(STR$(INT(RND * 10)), 1): NEXT i
RETURN

Adios:
PRINT "At least one value in CRnd input array is out of range!"
PRINT "Range for each value except the zero value is 0-255"
STOP: SYSTEM

END SUB


 
 Respond to this message   
 
< Previous Page 1 2 3 4 5 Next >
  << Previous Topic | Next Topic >>Return to Index  
 Copyright © 1999-2017 Network54. All rights reserved.   Terms of Use   Privacy Statement