# Algorithm

Encoding

  1. Convert the source and key to byte arrays.
  2. XOR each source byte with the corresponding key byte in order, repeating the key as necessary to match the length of the source.
  3. Encode the resulting byte array using the Base64 encoding scheme.

If the source is empty, the result is an empty string.
If the key is empty, the source is encoded using standard Base64 without XOR processing.

Decoding

Manipulate in the opposite way.

# Examples

Standard Base64

Source Text (UTF-8) a b c
Source octets 97 (0x61) 98 (0x62) 99 (0x63)
Bit pattern 0 1 1 0 0 0 0 1 0 1 1 0 0 0 1 0 0 1 1 0 0 0 1 1
Index 24 22 9 35
Base64-encoded Y W J j
Encoded octets 89 (0x59)
01011001
87 (0x57)
01010111
74 (0x4A)
01001010
106 (0x6A)
01101010

XB64 : src = abc / key = xyz (src.length = key.length)

Source Text (UTF-8) a b c
Octets 97 (0x61) 98 (0x62) 99 (0x63)
Bit pattern 0 1 1 0 0 0 0 1 0 1 1 0 0 0 1 0 0 1 1 0 0 0 1 1
Key Text (UTF-8) x y z
Octets 120 (0x78)121 (0x79)122 (0x7A)
Bit pattern 0 1 1 1 1 0 0 0 0 1 1 1 1 0 0 1 0 1 1 1 1 0 1 0
Bitwise op.   97 XOR 120 = 25 98 XOR 121 = 27 99 XOR 122 = 25
Bit pattern 0 0 0 1 1 0 0 1 0 0 0 1 1 0 1 1 0 0 0 1 1 0 0 1
Output Index 6 17 44 25
Base64-encoded G R s Z
Encoded octets 71 (0x47)
01000111
82 (0x52)
01010010
115 (0x73)
01110011
90 (0x5A)
01011010

XB64 : src = abcde / key = xyz (src.length > key.length)

Source Text (UTF-8) a b c d e
Octets 97 (0x61) 98 (0x62) 99 (0x63) 100 (0x64) 101 (0x65)
Bit pattern 0 1 1 0 0 0 0 1 0 1 1 0 0 0 1 0 0 1 1 0 0 0 1 1 0 1 1 0 0 1 0 0 0 1 1 0 0 1 0 1
Key Text (UTF-8) x y z x y
Octets 120 (0x78) 121 (0x79) 122 (0x7A) 120 (0x78) 121 (0x79)
Bit pattern 0 1 1 1 1 0 0 0 0 1 1 1 1 0 0 1 0 1 1 1 1 0 1 0 0 1 1 1 1 0 0 0 0 1 1 1 1 0 1 1
Bitwise op.   97 XOR 120 = 25 98 XOR 121 = 27 99 XOR 122 = 25 100 XOR 120 = 28 101 XOR 121 = 28 Base64 zero padding
Bit pattern 0 0 0 1 1 0 0 0 0 0 0 1 1 0 1 1 0 0 0 1 1 0 0 1 0 0 0 1 1 1 0 0 0 0 0 1 1 1 0 0 0 0 - - - - - -
Output Index 6 17 44 25 7 1 48 padding
Base64-encoded G R s Z H B w =
Encoded octets 71 (0x47)
01000111
82 (0x52)
01010010
115 (0x73)
01110011
90 (0x5A)
01011010
72 (0x48)
01001000
66 (0x42)
01000010
119 (0x77)
01110111
61 (0x3D)
00111101

XB64 : src = ab / key = xyz (src.length < key.length)

Source Text (UTF-8) a b
Octets 97 (0x61) 98 (0x62)
Bit pattern 0 1 1 0 0 0 0 1 0 1 1 0 0 0 1 0
Key Text (UTF-8) x y z
Octets 120 (0x78)121 (0x79)122 (0x7A)
Bit pattern 0 1 1 1 1 0 0 0 0 1 1 1 1 0 0 1 0 1 1 1 1 0 1 0
Bitwise op.   97 XOR 120 = 25 98 XOR 121 = 27 unused
Bit pattern 0 0 0 1 1 0 0 1 0 0 0 1 1 0 1 1 0 0 - - - - - -
Output Index 6 17 44 padding
Base64-encoded G R s =
Encoded octets 71 (0x47)
01000111
82 (0x52)
01010010
115 (0x73)
01110011
61 (0x3D)
00111101
If the source is shorter than the key, the portion of the key beyond the source length is unused.
Keys with the same prefix up to the source length produce the same result.
This behavior follows from the way the algorithm works and is by design.

# Implementation

Java, JavaScript, Python, PowerShell, VBA implementations are available on GitHub.

Apache Maven

JAR direct download
xb64-2.0.0.jar (3,528 bytes / Compiled with JDK8)
SHA-1: 31dcb4f7cad6cbb10982c6590edc3b71718096b3
SHA-256: a7184de660d495971301fae401b59364c4248812717e6ceed78ad337fdbe604c

# Notice

XB64 is intended for obfuscation, not for providing confidentiality.
The key is simply a parameter used in the reversible transformation; the scheme does not rely on it being secret.
This method should not be used where confidentiality must be assured.
x
The Base 64 Alphabet IDX BIN ENC IDX BIN ENC IDX BIN ENC IDX BIN ENC 0 000000 A 16 010000 Q 32 100000 g 48 110000 w 1 000001 B 17 010001 R 33 100001 h 49 110001 x 2 000010 C 18 010010 S 34 100010 i 50 110010 y 3 000011 D 19 010011 T 35 100011 j 51 110011 z 4 000100 E 20 010100 U 36 100100 k 52 110100 0 5 000101 F 21 010101 V 37 100101 l 53 110101 1 6 000110 G 22 010110 W 38 100110 m 54 110110 2 7 000111 H 23 010111 X 39 100111 n 55 110111 3 8 001000 I 24 011000 Y 40 101000 o 56 111000 4 9 001001 J 25 011001 Z 41 101001 p 57 111001 5 10 001010 K 26 011010 a 42 101010 q 58 111010 6 11 001011 L 27 011011 b 43 101011 r 59 111011 7 12 001100 M 28 011100 c 44 101100 s 60 111100 8 13 001101 N 29 011101 d 45 101101 t 61 111101 9 14 001110 O 30 011110 e 46 101110 u 62 111110 + 15 001111 P 31 011111 f 47 101111 v 63 111111 / (pad) =