Search code examples
c#encryptionuwpbluetooth-lowenergyaes

Cannot authenticate Mi Band 2


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.

  1. Main Auth Method with authentication level 1 (notification to band with needed touch response)

  2. Checking new updates of authCharacteristic and waiting new response from band. There is handle 2, 3 and 4 levels of Authentication.

  3. 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

Solution

  • 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.