3

I'm porting several thousand lines of cryptographic C# functions to a Java project. The C# code extensively uses unsigned values and bitwise operations.

I am aware of the necessary Java work-arounds to support unsigned values. However, it would be much more convenient if there were implementations of unsigned 32bit and 64bit Integers that I could drop into my code. Please link to such a library.

Quick google queries reveal several that are part of commercial applications:

3
  • By the way, I forgot to ask: What feature exactly are you looking for in these libraries that can't be done with something similar to what I wrote below? Commented Apr 10, 2011 at 3:19
  • @Mehrdad My misconceptions about Java may also have distorted what I assumed possible. I'll probably accept Thomas Pornin's answer for consolidating the common techniques - even though they are exactly what I was trying to avoid. Commented Apr 12, 2011 at 7:46
  • There honestly isn't much "expertise" involved in bitwise arithmetic; you can really do it yourself. Clever in what way, though? If you mean speed, that's one thing, but other than that, I think the issue is correctness, not cleverness. (And also, obviously accept Thomas's answer if you found that more helpful! :] ) Commented Apr 12, 2011 at 7:46

2 Answers 2

2

Operations with signed and unsigned integers are mostly identical, when using two's complement notation, which is what Java does. What this means is that if you have two 32-bit words a and b and want to compute their sum a+b, the same internal operation will produce the right answer regardless of whether you consider the words as being signed or unsigned. This will work properly for additions, subtractions, and multiplications.

The operations which must be sign-aware include:

  • Right shifts: a signed right shift duplicates the sign bit, while an unsigned right shift always inserts zeros. Java provides the ">>>" operator for unsigned right-shifting.
  • Divisions: an unsigned division is distinct from a signed division. When using 32-bit integers, you can convert the values to the 64-bit long type ("x & 0xFFFFFFFFL" does the "unsigned conversion" trick).
  • Comparisons: if you want to compare a with b as two 32-bit unsigned words, then you have two standard idioms:

    if ((a + Integer.MIN_VALUE) < (b + Integer.MIN_VALUE)) { ... }

    if ((a & 0xFFFFFFFFL) < (b & 0xFFFFFFFFL)) { ... }

Knowing that, the signed Java types are not a big hassle for cryptographic code. I have implemented many cryptographic primitives in Java, and the signed types are not an issue provided that you understand what you are writing. For instance, have a look at sphlib: this is an opensource library which implements many cryptographic hash functions, both in C and in Java. The Java code uses Java's signed types (int, long...) quite seamlessly, and it simply works.

Java does not have operator overloading, so Java-only "solutions" to get unsigned types will involve custom classes (such as the UInt64 class you link to), which will imply a massive performance penalty. You really do not want to do that.

Theoretically, one could define a Java-like language with unsigned types and implement a compiler which produces bytecode for the JVM (internally using the tricks I detail above for shifts, divisions and comparisons). I am not aware of any available tool which does that; and, as I said above, Java's signed types are just fine for cryptographic code (in other words, if you have trouble with such signed types, then I daresay that you do not know enough to implement cryptographic code securely, and you should refrain from doing so; instead, use existing opensource libraries).

Sign up to request clarification or add additional context in comments.

Comments

2

This is a language feature, not a library feature, so there is no way to extend Java to support this functionality unless you change the language itself, in which case you'd need to make your own compiler.

However, if you need unsigned right-shifts, Java supports the >>> operator which works like the >> operator for unsigned types.

You can, however, make your own methods to perform arithmetic with signed types as though they were unsigned; this should work, for example:

static int multiplyUnsigned(int a, int b)
{
    final bool highBitA = a < 0,    highBitB = b < 0;
    final long a2 = a & ~(1 << 31), b2 = b & ~(1 << 31);
    final long result = (highBitA ? a2 | (1 << 31) : a2)
                      * (highBitB ? b2 | (1 << 31) : b2);
    return (int)result;
}

Edit:

Thanks to @Ben's comment, we can simplify this:

static int multiplyUnsigned(int a, int b)
{
    final long mask = (1L << 32) - 1;
    return (int)((a & mask) * (b & mask));
}

Neither of these methods works, though, for the long type. You'd have to cast to a double, negate, multiply, and cast it back again in that case, which would likely kill any and all of your optimizations.

16 Comments

Thank you for your response, but I'm well aware of the >>> operator. I really would expect that it would be possible to implement and unsigned integer object within Java, including the necessary operator overloads. The docs for commercial projects such as this give me hope.
I don't think that multiply function returns anything resembling correct results when the high bit is set.
@Karl: Java does not support operator overloading. And for cryptographic purposes, objects would be very slow; you'd need primitive unsigned types, which do not exist in Java.
@Ben: Yeah you were right; I edited it, this one should work.
@Mehrdad: If you have a wider integral type, you can do simply long mask = (1L << 32) - 1; return (a & mask) * (b & mask); But that doesn't generalize to the widest integral type.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.