I need to implement as fast as possible left bit shift of a 16-byte array in JavaCard.
I tried this code:
private static final void rotateLeft(final byte[] output, final byte[] input) {
short carry = 0;
short i = (short) 16;
do {
--i;
carry = (short)((input[i] << 1) | carry);
output[i] = (byte)carry;
carry = (short)((carry >> 8) & 1);
} while (i > 0);
}
Any ideas how to improve the performace? I was thinking about some Util.getShort(...)
and Util.setShort(...)
magic, but I did not manage to make it work faster then the implementation above.
This is one part of CMAC subkeys computation and it is done quite often, unfortunately. In case you know some faster way to compute CMAC subkeys (both subkeys in one loop or something like that), please, let me know.
When it comes for speed, known length, hard-coded version is the fastest (but ugly). If you need to shift more than one bit, ensure to update the code accordingly.
And use RAM byte array!
It might help to cache CMAC subkeys when signing repeatedly using the same key (i.e. the same DESFire EV1 session key). The subkeys are always the same for the given key.
I think David's answer could be even faster if it used two local variables to cache the values read twice from the same offset of the input array (from my observations on JCOP, the array access is quite expensive even for transient arrays).
EDIT: I can provide the following implementation which does 4 bit right shift using short (32-bit int variant for cards supporting it would be even faster):
Beware, this code assumes same offsets in source and destination.
You can unroll this loop and use constant parameters if desired.
This is the fastest algorithm to rotate arbitrary number of bits I could come up with (I rotate array of 8 bytes, you can easily transform it to shifting 16 instead):
Use EEPROM to create a masking table for your shifts. Mask is just increasing amounts of 1s from the right:
Then you first use
Util.arrayCopyNonAtomic
for quick swap of bytes if shift is larger than 8:You can additionally remove
mask
variable and use direct reference to the table instead.Using this rather than naive implementation of bit-wise rotation proved to be about 450% - 500% faster.