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.