0

I've been provided with a java.util.String 32 characters length. The String contains 16 pairs of hexadecimal characters which represent the key that I should use on an AES and CMAC message signature creation.

I've a problem getting the correct message signed with the provided key, I'm using 'bouncycastle' library. I show you my code:

        KeyParameter parameter = new KeyParameter(KEY.getBytes(StandardCharsets.UTF_8));

        AESEngine aes = new AESEngine();
        CMac mac = new CMac(aes);
        mac.init(parameter);
        mac.update(message.getBytes(StandardCharsets.UTF_8), 0, message.getBytes(StandardCharsets.UTF_8).length);
        byte[] out = new byte[mac.getMacSize()];
        mac.doFinal(out, 0);

A partner is implementing this very code in C# with the same library. We found that byte in java has signed number representation although C# don't. Trying to make parallel implementation of this get's me a bit disoriented.

I'm able to get the proper int[] from 0 to 255 values that my partner gets when processing the key.

Antonio E.
  • 359
  • 1
  • 9
  • 27
  • 2
    Identical bit sequences are represented differently for an unsigned (C#) and signed (Java, two's complement) byte type, which is not a bug. Check the hex encoded values. If you want your implementation to be functionally identical to the C# code, you need to post the C# code so that a comparison is possible. If you just want to check your own implementation, you could use CMAC/AES test vectors, e.g. [here](https://github.com/ircmaxell/quality-checker/blob/master/tmp/gh_18/PHP-PasswordLib-master/test/Data/Vectors/cmac-aes.sp-800-38b.test-vectors). – Topaco Apr 22 '23 at 09:13
  • 1
    A (probable) bug is that your key seems to be hex encoded according to your description, but you UTF-8 encode it. Correct would be a hex decoding, e.g. with `HexFormat.of().parseHex()`. Whether this also applies to your message depends on your message (is it also hex encoded (as e.g. with the test vectors), or is it a text that should be UTF-8 encoded etc.?). Post (non-productive) sample data. – Topaco Apr 22 '23 at 09:15
  • @Topaco You gave me the clue, that was happening (a poor description of the data i've been provided) all of them the key and message should be hex decoded first and shouldn't be UTF-8 byte encoded. – Antonio E. Apr 23 '23 at 07:59

1 Answers1

0

I had a poor specification of the problem. My inputs happened to be hex encoded (each 2 characters from the string should be treated as an hex number representation, each pair had to be converted to the byte representation of the number).

This kind of encoding is also the usual way to represent the CMAC output so as a result I define 2 functions:


public static byte[] stringToByteHexpairs(String input){
    
    byte[] output= new byte[input.length()/2];
    int k = 0;
    for (int i = 0; i <= input.length() - 2 ; i += 2) {
         String par = input.substring(i, i+2);
         output[k] = (byte) Integer.parseInt(par,16);
         k++;
    }
    return output;
}

public static String bytesToHexString(byte[] array) {

    StringBuilder sb = new StringBuilder();
    for (int i = 0; i < array.length; i++) {
        sb.append(String.format("%02X",array[i]));
    }
    return sb.toString();
}

And I use it before in place of the wrong byte transformation on the code I provided. BONUS I also add the output transformation that is espected:

KeyParameter parameter = new KeyParameter(stringToByteHexpairs(KEY));
byte[] messageBytes = stringToByteHexpairs(message);

...

mac.update(messageBytes, 0, messageBytes.length);

...

mac.doFinal(out, 0);
return bytesToHexString(out);

Antonio E.
  • 359
  • 1
  • 9
  • 27