# Algorithm
Encoding
- Convert the source and key to byte arrays.
- XOR each source byte with the corresponding key byte in order, repeating the key as necessary to match the length of the source.
- 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.
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.