Skip to content

Commit

Permalink
Fixed bug when BigInteger overflows to 13th byte
Browse files Browse the repository at this point in the history
  • Loading branch information
bschoening committed Feb 10, 2025
1 parent 8b909db commit e6ca131
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 14 deletions.
26 changes: 12 additions & 14 deletions src/main/java/com/privacylogistics/FF3Cipher.java
Original file line number Diff line number Diff line change
Expand Up @@ -433,10 +433,16 @@ protected static byte[] calculateP(int i, String alphabet, byte[] W, char[] B) {

// The remaining 12 bytes of P are copied from reverse(B) with padding

byte[] bBytes = decode_int_r(B, alphabet).toByteArray();

System.arraycopy(bBytes, 0, P, (BLOCK_SIZE - bBytes.length), bBytes.length);
logger.trace("round: {} W: {} P: {}", () -> i, () -> byteArrayToHexString(W), () -> byteArrayToIntString(P));
BigInteger val = decode_int_r(B, alphabet);
byte[] bBytes = val.toByteArray();

// BigInteger's toByteArray may return a 13th sign byte, but we consider the value unsigned
if (bBytes.length > 12) {
System.arraycopy(bBytes, 1, P, (BLOCK_SIZE - 12), 12);
} else {
System.arraycopy(bBytes, 0, P, (BLOCK_SIZE - bBytes.length), bBytes.length);
}
logger.trace("round: {} P: {} W: {}", () -> i, () -> byteArrayToHexString(P), () -> byteArrayToHexString(W));
return P;
}

Expand All @@ -453,7 +459,7 @@ protected static String reverseString(String s) {
* Reverse a byte array in-place
* @param b a mutable byte array
*/
protected void reverseBytes(byte[] b) {
protected static void reverseBytes(byte[] b) {
for (int i = 0; i < b.length / 2; i++) {
byte temp = b[i];
b[i] = b[b.length - i - 1];
Expand All @@ -466,7 +472,7 @@ protected void reverseBytes(byte[] b) {
* @param s a character string containing hexadecimal digits
* @return a byte array with the values parsed from the string
*/
protected static byte[] hexStringToByteArray(String s) {
public static byte[] hexStringToByteArray(String s) {
byte[] data = new byte[s.length() / 2];
for (int i = 0; i < s.length(); i += 2) {
data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
Expand All @@ -490,14 +496,6 @@ protected static String byteArrayToHexString(byte[] byteArray) {
return new String(hexChars, StandardCharsets.UTF_8);
}

/**
* used for debugging output
* @param byteArray a byte array
* @return a decimal string encoding of a number
*/
protected static String byteArrayToIntString(byte[] byteArray) {
return Arrays.toString(byteArray);
}

/**
* Return a char[] representation of a number in the given base system
Expand Down
29 changes: 29 additions & 0 deletions src/test/java/com/privacylogistics/FF3CipherTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,18 @@ public void testDecodeInt() {
assertEquals(new BigInteger("2297305934914824457484538562"), (decode_int_r("2658354847544284194395037922".toCharArray(), "0123456789")));
}

@Test
public void testReverseBytes() {
byte [] mutableArray = new byte[] {1};
reverseBytes(mutableArray);
assertArrayEquals(new byte[]{1}, mutableArray);
mutableArray = new byte[] {1,2,3};
reverseBytes(mutableArray);
assertArrayEquals(new byte[]{3,2,1}, mutableArray);
mutableArray = new byte[] {1,2,3,4};
reverseBytes(mutableArray);
assertArrayEquals(new byte[]{4,3,2,1}, mutableArray);
}
@Test
public void testNistFF3() throws Exception {
// NIST FF3-AES 128, 192, 256
Expand Down Expand Up @@ -291,6 +303,23 @@ public void testGermanAlphabet() throws Exception {
assertEquals(pt, plaintext);
}

@Test
public void testDecodeIntHighByte() throws Exception {
// Test the German alphabet with a radix of 70. German consists of the latin alphabet
// plus four additional letters, each of which have uppercase and lowercase letters

String alphabet = FF3Cipher.ASCII_UPPERCASE + FF3Cipher.ASCII_LOWERCASE + DIGITS;
String key = "2DE79D232DF5585D68CE47882AE256D6";
String tweak = "CBD09280979564";
String pt = "Ceciestuntestdechiffrement123cet";
String ct = "0uaTPI9g49f9MMw54OvY8x5rmNcrhydM";
FF3Cipher c = new FF3Cipher(key, tweak, alphabet);
String ciphertext = c.encrypt(pt);
assertEquals(ct, ciphertext);
String plaintext = c.decrypt(ciphertext);
assertEquals(pt, plaintext);
}

@Test
void testTweakHasNoSideEffects() throws Exception {
String key = "EF4359D8D580AA4F7F036D6F04FC6A94";
Expand Down

0 comments on commit e6ca131

Please sign in to comment.