/* Copyright (C) 2020 Taavi Eomäe
This file is part of Gadgetbridge.
Gadgetbridge is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Gadgetbridge is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see .
*/
package nodomain.freeyourgadget.gadgetbridge.service.devices.nut;
import org.junit.Test;
import java.math.BigInteger;
import java.util.AbstractMap;
import java.util.Map;
import static junit.framework.TestCase.assertEquals;
import static junit.framework.TestCase.assertNotNull;
import static junit.framework.TestCase.fail;
import static nodomain.freeyourgadget.gadgetbridge.devices.nut.NutKey.byteArraysConcatReverseWithPad;
import static nodomain.freeyourgadget.gadgetbridge.devices.nut.NutKey.byteArraysDeConcatReverseWithPad;
import static nodomain.freeyourgadget.gadgetbridge.devices.nut.NutKey.bytesToHex2;
import static nodomain.freeyourgadget.gadgetbridge.devices.nut.NutKey.hexStringToByteArrayNut;
import static nodomain.freeyourgadget.gadgetbridge.devices.nut.NutKey.macAsByteArray;
import static nodomain.freeyourgadget.gadgetbridge.devices.nut.NutKey.passwordGeneration;
import static nodomain.freeyourgadget.gadgetbridge.devices.nut.NutKey.reversePasswordGeneration;
public class NutUtilsTest {
@Test
public void testPasswordGen() {
String result = bytesToHex2(passwordGeneration(
"00:00:00:00:00:00",
new byte[]{1, 0, 0, 0, 0, 0, 0},
BigInteger.ZERO,
BigInteger.ZERO)
);
String expected = bytesToHex2(new byte[]{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00});
assertEquals(expected, result);
}
@Test
public void testPasswordGen2() {
String result = bytesToHex2(passwordGeneration(
"00:00:00:00:00:00",
new byte[]{1, 0, 0, 0, 0, 0, 0},
BigInteger.ZERO,
BigInteger.ZERO)
);
String expected = bytesToHex2(new byte[]{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00});
assertEquals(expected, result);
}
@Test
public void testPasswordGen3() {
String result = bytesToHex2(passwordGeneration(
"00:00:00:00:00:00",
new byte[]{1, 1, 0, 0, 0, 0, 0},
BigInteger.ZERO,
BigInteger.ZERO)
);
String expected = bytesToHex2(new byte[]{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00});
assertEquals(expected, result);
}
@Test
public void testPasswordGen4() {
String result = bytesToHex2(passwordGeneration(
"00:00:00:00:00:00",
new byte[]{1, 0, 0, 0, 0, 0, 0},
new BigInteger(1, new byte[]{1, 0, 0, 0, 0, 0}),
BigInteger.ZERO)
);
String expected = bytesToHex2(new byte[]{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00});
assertEquals(expected, result);
}
@Test
public void testPasswordGen5() {
String result = bytesToHex2(passwordGeneration(
"00:00:00:00:00:00",
new byte[]{1, 0, 0, 0, 0, 0, 0, 0, 0},
BigInteger.ZERO,
new BigInteger(1, new byte[]{1, 1, 1, 1, 1, 1, 0, 0}))
);
String expected = bytesToHex2(new byte[]{0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00});
assertEquals(expected, result);
}
@Test
public void testPasswordGen6() {
String result = bytesToHex2(passwordGeneration(
"01:02:03:04:05:06",
new byte[]{1, 1, 2, 3, 4, 5, 6, 7, 8},
BigInteger.ZERO,
BigInteger.ZERO)
);
String expected = bytesToHex2(new byte[]{0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00});
assertEquals(expected, result);
}
@Test
public void testPasswordGen7() {
String result = bytesToHex2(passwordGeneration(
"01:02:03:04:05:06",
new byte[]{1, 1, 2, 3, 4, 5, 6, 7, 8},
new BigInteger(1, new byte[]{1, 2, 3, 4, 5, 6, 7, 8}),
new BigInteger(1, new byte[]{1, 2, 3, 4, 5, 6, 7, 8}))
);
String expected = bytesToHex2(new byte[]{0x17, 0x15, 0x13, 0x11, 0x0f, 0x0d, 0x0b, 0x0a, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01});
assertEquals(expected, result);
}
@Test
public void testReversePassword() {
String challenge = "01e8f0340d000000000000000000000000";
String response = "029bbd0fa25aed0000dcfd0c0000000000";
String device_mac = "ED:5A:94:CB:98:E4";
Map.Entry key = reversePasswordGeneration(
hexStringToByteArrayNut(challenge),
hexStringToByteArrayNut(response),
device_mac
);
assertNotNull(key);
assertEquals(new AbstractMap.SimpleEntry<>(new BigInteger("851420"), new BigInteger("996303")), key);
}
@Test
public void testPassword() {
String challenge = "011a9b826c000000000000000000000000";
String response = "02cd675d015bed0000dcfd0c0000000000";
String device_mac = "ED:5A:94:CB:98:E4";
Map.Entry key = new AbstractMap.SimpleEntry<>(new BigInteger("851420"), new BigInteger("996303"));
byte[] result = new byte[17];
result[0] = 0x02;
System.arraycopy(passwordGeneration(device_mac, hexStringToByteArrayNut(challenge), key.getKey(), key.getValue()), 0, result, 1, 16);
assertEquals(bytesToHex2(hexStringToByteArrayNut(response)), bytesToHex2(result));
}
@Test
public void testInvalidResponse() {
String challenge = "00";
String response = "00";
String device_mac = "0:00:00:00:00:00";
try {
reversePasswordGeneration(
hexStringToByteArrayNut(challenge),
hexStringToByteArrayNut(response),
device_mac
);
} catch (IllegalArgumentException e) {
// This is intended behaviour
assertNotNull(e);
return;
}
fail();
}
@Test
public void testHexToByteArray() {
byte[] arr = hexStringToByteArrayNut("0x0000000000");
assertEquals(bytesToHex2(new byte[]{0x00, 0x00, 0x00, 0x00, 0x00}), bytesToHex2(arr));
}
@Test
public void testHexToByteArray2() {
byte[] arr = hexStringToByteArrayNut("cafebabe");
assertEquals(bytesToHex2(new byte[]{(byte) 0xca, (byte) 0xfe, (byte) 0xba, (byte) 0xbe}), bytesToHex2(arr));
}
@Test
public void testMACToByteArray() {
byte[] arr = macAsByteArray("AA:BB:CC:DD:EE:FF");
assertEquals(bytesToHex2(
new byte[]{
(byte) 0xaa,
(byte) 0xbb,
(byte) 0xcc,
(byte) 0xdd,
(byte) 0xee,
(byte) 0xff
}
), bytesToHex2(arr));
}
@Test
public void testConcat() {
byte[] src1 = new byte[]{1, 2, 3, 4, 5, 6, 7, 8};
byte[] src2 = new byte[]{9, 10, 11, 12, 13, 14, 15, 16};
assertEquals(
bytesToHex2(new byte[]{0x10, 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01}),
bytesToHex2(byteArraysConcatReverseWithPad(
src1,
src2)
)
);
}
@Test
public void testConcatDeConcat() {
byte[] src1 = new byte[]{0, 0, 3, 4, 5, 6, 0, 0};
byte[] src2 = new byte[]{0, 0, 7, 8, 9, 1, 0, 0};
byte[] dst1 = new byte[8];
byte[] dst2 = new byte[8];
byteArraysDeConcatReverseWithPad(
byteArraysConcatReverseWithPad(
src1,
src2
),
dst1,
dst2
);
assertEquals(bytesToHex2(src1), bytesToHex2(dst1));
assertEquals(bytesToHex2(src2), bytesToHex2(dst2));
}
@Test
public void testConcatDeConcat2() {
byte[] src1 = new byte[]{1, 2, 3, 4, 5, 6, 7, 8};
byte[] src2 = new byte[]{9, 10, 11, 12, 13, 14, 15, 16};
byte[] dst1 = new byte[8];
byte[] dst2 = new byte[8];
byteArraysDeConcatReverseWithPad(
byteArraysConcatReverseWithPad(
src1,
src2
),
dst1,
dst2
);
assertEquals(bytesToHex2(src1), bytesToHex2(dst1));
assertEquals(bytesToHex2(src2), bytesToHex2(dst2));
}
}