# Cryptopals first challenge – hexadecimal to base64

Posted on

Problem

I’ve just started the cryptopals-challenge, and now wanted to show my solution to the first challenge here:

``````public class Challenge1_1 {

public static void main(String[] args) {
String hex = "49276d206b696c6c696e6720796f757220627261696e206c696b65206120706f69736f6e6f7573206d757368726f6f6d";
String base64 = hextobase64(hex);
System.out.println(base64);
String test = "SSdtIGtpbGxpbmcgeW91ciBicmFpbiBsaWtlIGEgcG9pc29ub3VzIG11c2hyb29t";
boolean t = base64.equals(test);
System.out.println(t);
}

public static String hextobase64(String hex) {

String[] hex_array = new String[hex.length()/2];

//Splits up the hex String into substring with length 2
for(int i = 0; i < hex_array.length; i++) {
int x = 2 * i;
int y = x + 2;
hex_array[i] = substring(hex, x, y);
}

//Conversion to binary system
String binary = "";
String bin = "";
for(int i = 0; i < hex_array.length; i++) {
bin = conversion(hex_array[i]);
while(bin.length()<8){
bin = "0" + bin;
}
binary = binary + bin;
}

//Split up to strings of length 6
String[] binary6 = new String[binary.length()/6];
for(int i = 0; i < binary6.length; i++) {
int x = i * 6;
int y = x + 6;
binary6[i] = substring(binary, x, y);
}

//Conversion to base64
String out = "";
String character = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
String[] base64 = {
"000000", "000001", "000010", "000011", "000100", "000101", "000110", "000111", "001000", "001001", "001010", "001011", "001100", "001101", "001110", "001111",
"010000", "010001", "010010", "010011", "010100", "010101", "010110", "010111", "011000", "011001", "011010", "011011", "011100", "011101", "011110", "011111",
"100000", "100001", "100010", "100011", "100100", "100101", "100110", "100111", "101000", "101001", "101010", "101011", "101100", "101101", "101110", "101111",
"110000", "110001", "110010", "110011", "110100", "110101", "110110", "110111", "111000", "111001", "111010", "111011", "111100", "111101", "111110", "111111"
};
for(int i = 0; i < binary6.length; i++) {
for(int j = 0; j < base64.length; j++) {
if(binary6[i].equals(base64[j])){
out = out + character.charAt(j);
}
}
}
return(out);
}

public static String conversion(String hex) {
//hex-system to decimal system
String hex_numbers = "0123456789ABCDEF";
hex = hex.toUpperCase();
int value = 0;
for (int i = 0; i < hex.length(); i++)
{
int d = hex_numbers.indexOf(hex.charAt(i));
value = 16*value + d;
}

//decimal to binary
String out = "";
while(value != 0){
int mod = value%2;
String m = mod + "";
value = value/2;
out = m + out;

}
return out;

}

public static String substring(String str, int start, int end) {

String out = "";
if (start > end) {
return out;
}

if (start < 0) {
start = 0;
}

if (end > str.length() - 1) {
end = str.length();
}

while (start < end) {
out = out + str.charAt(start);
start = start + 1;
}

return out;

}
}

``````

I’ve tried to all do it manually instead of using some kind of java-package.
I would appreciate any suggestions to improve the code.

Solution

That is a very pure solution that does not use any available feature. It is a solid solution.

However everything is String, even the conversion from a byte as two hexadecimal digits uses integer, but converts it back to a string.

The same code style of yours would allow immediately convert every hexadecimal digit to 4 bits.

``````    final String[] nibbles = { "0000", "0001", "0010", "0011",
"0100", "0101", "0110", "0111",
"1000", "1001", "1010", "1011",
"1100", "1101", "1110", "1111" };
int nbitsRaw = hex.length() * 4;

// Make nbits a multiple of 6
int nbits += (6 - (nbitsRaw % 6)) % 6;
StringBuilder sb = new StringBuilder(nbits);
hex.codePoints()
.forEach(hexdigit -> {
int value = hexdigit <= '9' ? hexdigit - '0' : 9 + (hexdigit & 0xF); // 0-9A-Fa-F
sb.append(nibbles[value]);
});
for (int i = nbitsRaw; i < nbits; ++i) {
sb.append('0');
}
``````

Best of course would be using the bits in an `int`, not needing to juggle string constants of binary numbering. Especially the loops hurt. One would indeed far better use a `Map<String, Character>` but I understand your requirement of not using any higher construct.

The code is necessarily slow. You can try a longer input, and will probably have to wait for a result.

String concatenation is slow; `char[]` or `StringBuilder` would be advisable.
One can always do `new String(charArray)`.

Stylistic:

• `hextobase64` by java camel case convention: `hexToBase64`
• `conversion` no-namer: `hexByteToBits`
• The constants could be fields `private static final String[] BASE64` i.o. base64.