Base64 Encoding and Decoding (BASLOAD example)
Posted: Thu Jun 20, 2024 6:13 am
Here is an approach for doing "Base64" encoding (as described here). This is different than base-N radix conversion.
To test results with a known reference, see here.
Save this as BASE64ENC.BASL,
then do:
BASLOAD "BASE64ENC.BASL"
RUN
This is using a set of "safe printable characters" in a string to transfer binary data between systems (where normally that binary data might contain non-printable characters that end up interpreted as control codes for the systems involved; so we get around that by converting it to these printable characters, and decoding it back to the original binary after the transfer-- much like how image file attachments work in e-mails).
This version only supports alpha-numeric string input of up to 31 characters. This is not at all an optimized approach, but intended more to show the workflow involved (of breaking the input data into chunks of 6-bits and handling with the ending pad at needed).
Attached is the tokenized BASIC version that you can use LOAD with (instead of BASLOAD).
To test results with a known reference, see here.
Save this as BASE64ENC.BASL,
then do:
BASLOAD "BASE64ENC.BASL"
RUN
This is using a set of "safe printable characters" in a string to transfer binary data between systems (where normally that binary data might contain non-printable characters that end up interpreted as control codes for the systems involved; so we get around that by converting it to these printable characters, and decoding it back to the original binary after the transfer-- much like how image file attachments work in e-mails).
This version only supports alpha-numeric string input of up to 31 characters. This is not at all an optimized approach, but intended more to show the workflow involved (of breaking the input data into chunks of 6-bits and handling with the ending pad at needed).
Code: Select all
PRINT "ENTER ALPHA-NUMERIC CONTENT TO ENCODE:"
INPUT A$
GOSUB ENCODE64.INIT
REM =============================================
MAIN.LOOP:
ENCODE.STR$ = A$ : REM MAKE COPY OF INPUT STRING
GOSUB DO.ENCODE64 : REM RESULT IN ENCODE64.RES$ AND BIN.SEQUENCE$
PRINT ENCODE64.RES$
END
GOTO MAIN.LOOP
REM =============================================
REM EXAMPLE:
REM "THE Q" (AS IN: "THE QUICK BROWN FOX")
REM $54 $48 $45 $20 $51
REM 0101 0100 0100 1000 0100 0101 0010 0000 0101 0001
REM T H E _ Q
REM 010101 000100 100001 000101 001000 000101 000100 =
REM V E h F I F E..
REM
REM ====================================================
REM INPUT ENCODE.STR$
DO.ENCODE64:
BIN.SEQUENCE$=""
X.LEN = LEN(ENCODE.STR$)
FOR I = 1 TO X.LEN
N = ASC( MID$(ENCODE.STR$,I,1) ) : REM CONVERT EACH CHAR OF THE INPUT STRING TO ASCII NUMERIC
REM CONVERT ASCII NUMERIC TO AN 8-CHAR PADDED BINARY SEQUENCE STRING
B7$="0":B6$="0":B5$="0":B4$="0":B3$="0":B2$="0":B1$="0":B0$="0"
IF N AND $80 THEN B7$="1"
IF N AND $40 THEN B6$="1"
IF N AND $20 THEN B5$="1"
IF N AND $10 THEN B4$="1"
IF N AND $08 THEN B3$="1"
IF N AND $04 THEN B2$="1"
IF N AND $02 THEN B1$="1"
IF N AND $01 THEN B0$="1"
BIN.SEQUENCE$ = BIN.SEQUENCE$ + B7$ + B6$ + B5$ + B4$ + B3$ + B2$ + B1$ + B0$
NEXT I
X.LEN = LEN(BIN.SEQUENCE$)
PAD=0
IDX = X.LEN - INT(X.LEN/6)*6 : REM MODULUS
IF IDX=4 THEN PAD=1 : BIN.SEQUENCE$ = BIN.SEQUENCE$ + "00"
IF IDX=2 THEN PAD=2 : BIN.SEQUENCE$ = BIN.SEQUENCE$ + "0000"
ENCODE64.RES$ = ""
I = 1
DO.ENCODE64.NEXTGROUP:
TMP$ = MID$(BIN.SEQUENCE$, I, 6)
PRINT TMP$
X = 0
IF MID$(TMP$, 1, 1) = "1" THEN X = X OR 32
IF MID$(TMP$, 2, 1) = "1" THEN X = X OR 16
IF MID$(TMP$, 3, 1) = "1" THEN X = X OR 8
IF MID$(TMP$, 4, 1) = "1" THEN X = X OR 4
IF MID$(TMP$, 5, 1) = "1" THEN X = X OR 2
IF MID$(TMP$, 6, 1) = "1" THEN X = X OR 1
ENCODE64.RES$ = ENCODE64.RES$ + E642A$(X)
I = I+6
IF I >= LEN(BIN.SEQUENCE$) THEN GOTO ENCODE64.DONE
GOTO DO.ENCODE64.NEXTGROUP
ENCODE64.DONE:
IF PAD > 0 THEN ENCODE64.RES$ = ENCODE64.RES$ + "=" : PAD=PAD-1 : GOTO ENCODE64.DONE
RETURN
ENCODE64.INIT:
DIM E642A$(63) : REM INDEX 0-64 Encode64 to ASCII
E642A$( 0) = "A"
E642A$( 1) = "B"
E642A$( 2) = "C"
E642A$( 3) = "D"
E642A$( 4) = "E"
E642A$( 5) = "F"
E642A$( 6) = "G"
E642A$( 7) = "H"
E642A$( 8) = "I"
E642A$( 9) = "J"
E642A$(10) = "K"
E642A$(11) = "L"
E642A$(12) = "M"
E642A$(13) = "N"
E642A$(14) = "O"
E642A$(15) = "P"
E642A$(16) = "Q"
E642A$(17) = "R"
E642A$(18) = "S"
E642A$(19) = "T"
E642A$(20) = "U"
E642A$(21) = "V"
E642A$(22) = "W"
E642A$(23) = "X"
E642A$(24) = "Y"
E642A$(25) = "Z"
E642A$(26) = "a"
E642A$(27) = "b"
E642A$(28) = "c"
E642A$(29) = "d"
E642A$(30) = "e"
E642A$(31) = "f"
E642A$(32) = "g"
E642A$(33) = "h"
E642A$(34) = "i"
E642A$(35) = "j"
E642A$(36) = "k"
E642A$(37) = "l"
E642A$(38) = "m"
E642A$(39) = "n"
E642A$(40) = "o"
E642A$(41) = "p"
E642A$(42) = "q"
E642A$(43) = "r"
E642A$(44) = "s"
E642A$(45) = "t"
E642A$(46) = "u"
E642A$(47) = "v"
E642A$(48) = "w"
E642A$(49) = "x"
E642A$(50) = "y"
E642A$(51) = "z"
E642A$(52) = "0"
E642A$(53) = "1"
E642A$(54) = "2"
E642A$(55) = "3"
E642A$(56) = "4"
E642A$(57) = "5"
E642A$(58) = "6"
E642A$(59) = "7"
E642A$(60) = "8"
E642A$(61) = "9"
E642A$(62) = "+"
E642A$(63) = "/"
RETURN