' Cipher algorithms: Caesar, ROT13, substitution, XOR, Vigenere
#COMPILE EXE
#DIM ALL

FUNCTION CaesarEncrypt(BYVAL text AS STRING, BYVAL shift AS LONG) AS STRING
    LOCAL i  AS LONG
    LOCAL c  AS LONG
    LOCAL n  AS LONG
    LOCAL result AS STRING
    shift = shift MOD 26
    IF shift < 0 THEN shift = shift + 26
    n = LEN(text)
    result = text
    FOR i = 1 TO n
        c = ASC(MID$(text, i, 1))
        IF c >= 65 AND c <= 90 THEN
            c = ((c - 65 + shift) MOD 26) + 65
            MID$(result, i, 1) = CHR$(c)
        ELSEIF c >= 97 AND c <= 122 THEN
            c = ((c - 97 + shift) MOD 26) + 97
            MID$(result, i, 1) = CHR$(c)
        END IF
    NEXT i
    FUNCTION = result
END FUNCTION

FUNCTION ROT13(BYVAL text AS STRING) AS STRING
    FUNCTION = CaesarEncrypt(text, 13)
END FUNCTION

FUNCTION BuildSubstitutionCipher(BYVAL key AS STRING) AS STRING
    LOCAL i  AS LONG
    LOCAL c  AS LONG
    LOCAL seen AS STRING
    LOCAL cipher AS STRING
    cipher = ""
    seen = SPACE$(256)
    key = UCASE$(key)
    FOR i = 1 TO LEN(key)
        c = ASC(MID$(key, i, 1))
        IF c >= 65 AND c <= 90 THEN
            IF ASC(MID$(seen, c + 1, 1)) = 0 THEN
                cipher = cipher + CHR$(c)
                MID$(seen, c + 1, 1) = CHR$(1)
            END IF
        END IF
    NEXT i
    FOR c = 65 TO 90
        IF ASC(MID$(seen, c + 1, 1)) = 0 THEN
            cipher = cipher + CHR$(c)
        END IF
    NEXT c
    FUNCTION = cipher
END FUNCTION

FUNCTION SubstEncrypt(BYVAL text AS STRING, BYVAL cipherKey AS STRING) AS STRING
    LOCAL i  AS LONG
    LOCAL c  AS LONG
    LOCAL result  AS STRING
    LOCAL cipher  AS STRING
    cipher = BuildSubstitutionCipher(cipherKey)
    result = UCASE$(text)
    FOR i = 1 TO LEN(result)
        c = ASC(MID$(result, i, 1))
        IF c >= 65 AND c <= 90 THEN
            MID$(result, i, 1) = MID$(cipher, c - 64, 1)
        END IF
    NEXT i
    FUNCTION = result
END FUNCTION

FUNCTION XOREncrypt(BYVAL text AS STRING, BYVAL key AS STRING) AS STRING
    LOCAL i  AS LONG
    LOCAL ki  AS LONG
    LOCAL kLen  AS LONG
    LOCAL result AS STRING
    result = text
    kLen = LEN(key)
    IF kLen = 0 THEN FUNCTION = text: EXIT FUNCTION
    ki = 1
    FOR i = 1 TO LEN(text)
        MID$(result, i, 1) = CHR$(ASC(MID$(text, i, 1)) XOR ASC(MID$(key, ki, 1)))
        ki = ki + 1
        IF ki > kLen THEN ki = 1
    NEXT i
    FUNCTION = result
END FUNCTION

FUNCTION VigenereEncrypt(BYVAL text AS STRING, BYVAL key AS STRING) AS STRING
    LOCAL i  AS LONG
    LOCAL ki  AS LONG
    LOCAL kLen  AS LONG
    LOCAL t  AS LONG
    LOCAL c  AS LONG
    LOCAL result AS STRING
    result = ""
    kLen = LEN(key)
    IF kLen = 0 THEN FUNCTION = text: EXIT FUNCTION
    ki = 1
    FOR i = 1 TO LEN(text)
        c = ASC(MID$(text, i, 1))
        t = ASC(UCASE$(MID$(key, ki, 1))) - 65
        IF c >= 65 AND c <= 90 THEN
            c = ((c - 65 + t) MOD 26) + 65
            ki = ki + 1
            IF ki > kLen THEN ki = 1
        ELSEIF c >= 97 AND c <= 122 THEN
            c = ((c - 97 + t) MOD 26) + 97
            ki = ki + 1
            IF ki > kLen THEN ki = 1
        END IF
        result = result + CHR$(c)
    NEXT i
    FUNCTION = result
END FUNCTION

FUNCTION VigenereDecrypt(BYVAL text AS STRING, BYVAL key AS STRING) AS STRING
    LOCAL i  AS LONG
    LOCAL ki  AS LONG
    LOCAL kLen  AS LONG
    LOCAL t  AS LONG
    LOCAL c  AS LONG
    LOCAL result AS STRING
    result = ""
    kLen = LEN(key)
    IF kLen = 0 THEN FUNCTION = text: EXIT FUNCTION
    ki = 1
    FOR i = 1 TO LEN(text)
        c = ASC(MID$(text, i, 1))
        t = ASC(UCASE$(MID$(key, ki, 1))) - 65
        IF c >= 65 AND c <= 90 THEN
            c = ((c - 65 - t + 26) MOD 26) + 65
            ki = ki + 1
            IF ki > kLen THEN ki = 1
        ELSEIF c >= 97 AND c <= 122 THEN
            c = ((c - 97 - t + 26) MOD 26) + 97
            ki = ki + 1
            IF ki > kLen THEN ki = 1
        END IF
        result = result + CHR$(c)
    NEXT i
    FUNCTION = result
END FUNCTION

FUNCTION PBMAIN() AS LONG
    LOCAL plain  AS STRING
    LOCAL enc  AS STRING
    LOCAL dec  AS STRING
    LOCAL key  AS STRING
    PRINT "=== String Cipher Algorithms ==="
    PRINT
    plain = "Hello World from PBXB64"
    PRINT "Original: " + plain
    PRINT
    enc = CaesarEncrypt(plain, 3)
    PRINT "Caesar(+3): " + enc
    PRINT "Caesar(-3): " + CaesarEncrypt(enc, -3)
    PRINT
    enc = ROT13(plain)
    PRINT "ROT13: " + enc
    PRINT "ROT13 again: " + ROT13(enc)
    PRINT
    key = "SECRET"
    enc = SubstEncrypt(plain, key)
    PRINT "Substitution(key=" + key + "): " + enc
    PRINT
    key = "XORKEY"
    enc = XOREncrypt(plain, key)
    PRINT "XOR encrypt: " + enc
    dec = XOREncrypt(enc, key)
    PRINT "XOR decrypt: " + dec
    PRINT
    key = "VIGENE"
    enc = VigenereEncrypt(plain, key)
    PRINT "Vigenere encrypt(key=" + key + "): " + enc
    dec = VigenereDecrypt(enc, key)
    PRINT "Vigenere decrypt: " + dec
    PRINT
    PRINT "Cipher operations complete."
    FUNCTION = 0
END FUNCTION
