I tried to connect and authenticate app with Mi Band 2, but on the last step (sending encryption key and receive successful authentication response) i receive error response. First, Second and Third steps are successfully, no exceptions. Here is all code of Authentication.
Main Auth Method with authentication level 1 (notification to band with needed touch response)
Checking new updates of authCharacteristic and waiting new response from band. There is handle 2, 3 and 4 levels of Authentication.
Encryption to AES/ECB/NoPadding encryption (i also tried AesCbc, but i have same result).
public async Task<bool> Authenticate()
{
var authCharacteristic = await Gatt.GetCharacteristicByServiceUuid(new Guid("0000FEE1-0000-1000-8000-00805F9B34FB"), new Guid("00000009-0000-3512-2118-0009af100700"));
// Subscribe to notifications
await authCharacteristic.WriteClientCharacteristicConfigurationDescriptorAsync(GattClientCharacteristicConfigurationDescriptorValue.Notify);
// Level 1
Debug.WriteLine("Level 1 started");
byte[] secretKey = new byte[] { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45 };
List<byte> sendKey = new List<byte>();
sendKey.Add(1);
sendKey.Add(8);
sendKey.AddRange(secretKey);
if (await authCharacteristic.WriteValueAsync(sendKey.ToArray().AsBuffer()) == GattCommunicationStatus.Success)
{
Debug.WriteLine("Level 1 success");
authCharacteristic.ValueChanged += authCharacteristic_ValueChanged;
}
return isAuthed;
}
private async void authCharacteristic_ValueChanged(GattCharacteristic sender, GattValueChangedEventArgs args)
{
var authCharacteristic = await Gatt.GetCharacteristicByServiceUuid(new Guid("0000FEE1-0000-1000-8000-00805F9B34FB"), new Guid("00000009-0000-3512-2118-0009af100700"));
if (sender.Uuid.ToString() == "00000009-0000-3512-2118-0009af100700")
{
Debug.WriteLine("Received characteristic value: " + args.CharacteristicValue.ToArray().ToList()[0]);
Debug.WriteLine("Received SendKey: " + args.CharacteristicValue.ToArray().ToList()[1]);
Debug.WriteLine("Received Status: " + args.CharacteristicValue.ToArray().ToList()[2]);
var request = args.CharacteristicValue.ToArray().ToList();
byte authResponse = 0x10;
byte authSendKey = 0x01;
byte authRequestRandomAuthNumber = 0x02;
byte authRequestEncryptedKey = 0x03;
byte authSuccess = 0x01;
byte authFail = 0x04;
if (request[0] == authResponse && request[1] == authSendKey && request[2] == authSuccess)
{
Debug.WriteLine("Level 2 started");
List<byte> authNumber = new List<byte>();
authNumber.Add(0x02);
authNumber.Add(0x08);
if (await authCharacteristic.WriteValueAsync(authNumber.ToArray().AsBuffer()) == GattCommunicationStatus.Success)
Debug.WriteLine("Level 2 success");
}
else if (request[0] == authResponse && request[1] == authRequestRandomAuthNumber && request[2] == authSuccess)
{
Debug.WriteLine("Level 3 started");
List<byte> randomKey = new List<byte>();
List<byte> relevantResponsePart = new List<byte>();
var responseValue = args.CharacteristicValue.ToArray();
for (int i = 0; i < responseValue.Count(); i++)
{
if (i >= 3)
relevantResponsePart.Add(responseValue[i]);
}
randomKey.Add(0x03);
randomKey.Add(0x08);
randomKey.AddRange(Encrypt(relevantResponsePart.ToArray()));
if (await authCharacteristic.WriteValueAsync(randomKey.ToArray().AsBuffer()) == GattCommunicationStatus.Success)
Debug.WriteLine("Level 3 success");
}
else if (request[0] == authResponse && request[1] == authRequestEncryptedKey && request[2] == authSuccess)
{
// Can't reach this code. Last byte is 4 (error).
Debug.WriteLine("Auth completed");
isAuthed = true;
}
}
}
public byte[] Encrypt(byte[] data)
{
byte[] secretKey = new byte[] { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45 };
string aesKey = Convert.ToBase64String(secretKey);
IBuffer key = Convert.FromBase64String(aesKey).AsBuffer();
SymmetricKeyAlgorithmProvider algorithmProvider = SymmetricKeyAlgorithmProvider.OpenAlgorithm(SymmetricAlgorithmNames.AesEcb);
CryptographicKey ckey = algorithmProvider.CreateSymmetricKey(key);
IBuffer buffEncrypt = CryptographicEngine.Encrypt(ckey, data.AsBuffer(), null);
return buffEncrypt.ToArray();
}
All debug messages in console here:
Connected to MI Band 2
Level 1 started
Level 1 success
Received characteristic value: 16
Received SendKey: 1
Received Status: 1
Level 2 started
Level 2 success
Received characteristic value: 16
Received SendKey: 2
Received Status: 1
Level 3 started
Level 3 success
Received characteristic value: 16
Received SendKey: 3
Received Status: 4
Problem was solved, when i change strings in Encryption()
byte[] secretKey = new byte[] { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45 };
IBuffer key = secretKey.AsBuffer();
I think my problem was in wrong Encryption code.