REM > SpellMaster
REM
REM SpellMaster encryption simulator in BBC BASIC
REM Version 1.00 (03 Aug 2022)
REM Crypto Museum, Paul Reuvers
REM
REM Requires !Reporter to run.
ON ERROR PROCerror : END
CODEWORDSIZE = 8
DIM CodeWord% CODEWORDSIZE + 1
Alphabet$ = "ABCDEFGHIJKLMNOPQRSTUVWXYZ?"
Enc$ = "HOWASMJRNEDGBXKTCQPUIYFZLV[\"
Dec$ = " "
PROCcreate_dec
*report
s$ = FN_enc("AAAAAAAA", "AAAAAAAAAA")
s$ = FN_dec("AAAAAAAA", s$)
*report
s$ = FN_enc("CATS", "DOGSDOGSDOGSDOGS")
s$ = FN_dec("CATS", s$)
END
DEF FN_enc(key$, pt$)
LOCAL i%, j%, k%, key%, r%, ct$, m%, m$
PROCexpand_key(CodeWord%, key$)
FOR i% = 1 TO LEN(pt$)
m% = INSTR(Alphabet$, MID$(pt$, i%, 1))
m$ = MID$(Enc$, m%, 1)
m% = ASC(m$)  65
REM calculate key
key% = 0
FOR j% = 0 TO CODEWORDSIZE  1
key% += (CodeWord%?j%)  65
IF key% < 128 THEN key% += 256
IF key% >= 128 THEN key% = 256
NEXT
key% = FNmod(key%, 28)
REM apply key
r% = FNmod(key%  m%, 28)
ct$ += MID$(Alphabet$, r% + 1, 1)
REM modify key
FOR j% = 1 TO CODEWORDSIZE  1
CodeWord%?(j%1) = CodeWord%?j%
NEXT
CodeWord%?(CODEWORDSIZE  1) = FNmod(key% + m%, 28)
NEXT
*report Encoding: key$ pt$ ">" ct$
=ct$
DEF FN_dec(key$, ct$)
LOCAL i%, j%, k%, key%, r%, pt$, m%, m$
PROCexpand_key(CodeWord%, key$)
FOR i% = 1 TO LEN(ct$)
m% = ASC(MID$(ct$, i%, 1))  65
IF m% = 2 THEN m% = 27
IF m% = 20 THEN m% = 26
REM calculate key
key% = 0
FOR j% = 0 TO CODEWORDSIZE  1
key% += (CodeWord%?j%)  65
IF key% < 128 THEN key% += 256
IF key% >= 128 THEN key% = 256
NEXT
key% = FNmod(key%, 28)
REM apply key
r% = FNmod(key%  m%, 28)
pt$ += MID$(Dec$, r% + 1, 1)
REM modify key
FOR j% = 1 TO CODEWORDSIZE  1
CodeWord%?(j%1) = CodeWord%?j%
NEXT
CodeWord%?(CODEWORDSIZE  1) = FNmod(key% + r%, 28)
NEXT
*report Decoding: key$ pt$ "<" ct$
=pt$
DEF PROCcreate_dec
LOCAL i%
Dec$ = STRING$(28, " ")
FOR i% = 1 TO 28
MID$(Dec$, ASC(MID$(Enc$, i%, 1))  64, 1) = CHR$(i% + 64)
NEXT
ENDPROC
DEF PROCexpand_key(loc%, key$)
LOCAL i%, j%, c%, len%
len% = LEN(key$)
FOR i% = 0 TO CODEWORDSIZE  1
c% = ASC(MID$(key$, j%+1, 1)) AND NOT 32
IF c% >= 65 AND c% <= 90 THEN
loc%?i% = c%
ELSE
ERROR 1,"Illegal character in keyword"
ENDIF
j% += 1
IF j% >= len% THEN j% = 0
NEXT
ENDPROC
DEF FNmod(val%, mod%)
IF val% > 0 THEN =val% MOD mod%
WHILE val% < 0
val% += mod%
ENDWHILE
=val%
DEF PROCerror
LOCAL error$
error$ = REPORT$+" at line " + STR$(ERL)
*report error$
ENDPROC
