예제 #1
0
        // 미밴드 인증
        async public void Authenticate(OnAuthHandler callback = null)
        {
            GattDeviceServicesResult servicesResult = await manager.Device.GetGattServicesForUuidAsync(new Guid(ATS_UUID));

            if (servicesResult.Status == GattCommunicationStatus.Success && servicesResult.Services.Count > 0)
            {
                GattDeviceService service = servicesResult.Services[0];

                GattCharacteristicsResult characteristicsResult = await service.GetCharacteristicsForUuidAsync(new Guid(ATC_UUID));

                if (characteristicsResult.Status == GattCommunicationStatus.Success && characteristicsResult.Characteristics.Count > 0)
                {
                    GattCharacteristic characteristic = characteristicsResult.Characteristics[0];

                    // Enable notification
                    GattCommunicationStatus status = await characteristic.WriteClientCharacteristicConfigurationDescriptorAsync(GattClientCharacteristicConfigurationDescriptorValue.Notify);

                    if (status == GattCommunicationStatus.Success)
                    {
                        characteristic.ValueChanged += (GattCharacteristic sender, GattValueChangedEventArgs args) => {
                            var    reader      = DataReader.FromBuffer(args.CharacteristicValue);
                            byte[] messageType = new byte[3]; reader.ReadBytes(messageType);

                            if (messageType[1] == 0x01) // Request random number
                            {
                                if (messageType[2] == 0x01)
                                {
                                    manager.Write(sender, new byte[] { 0x02, 0x08 });
                                }
                                else
                                {
                                    callback.Invoke(this, false);
                                    service.Dispose();
                                }
                            }
                            else if (messageType[1] == 0x02) // Get random number
                            {
                                byte[] number = new byte[reader.UnconsumedBufferLength];
                                reader.ReadBytes(number);

                                // Encrypt number
                                byte[] encNumber;
                                using (Aes aes = Aes.Create()) {
                                    aes.Key     = _authKey;
                                    aes.Mode    = CipherMode.ECB;
                                    aes.Padding = PaddingMode.None;

                                    ICryptoTransform encryptor = aes.CreateEncryptor(aes.Key, new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }); // Constant iv, bad :(
                                    using (MemoryStream stream = new MemoryStream()) {
                                        using (CryptoStream cryptoStream = new CryptoStream(stream, encryptor, CryptoStreamMode.Write)) {
                                            cryptoStream.Write(number, 0, number.Length);
                                            cryptoStream.FlushFinalBlock();
                                            encNumber = stream.ToArray();
                                        }
                                    }
                                }

                                // Send encrypted number
                                using (var stream = new MemoryStream()) {
                                    stream.Write(new byte[] { 0x03, 0x08 }, 0, 2);
                                    stream.Write(encNumber, 0, encNumber.Length);
                                    manager.Write(characteristic, stream.ToArray());
                                }
                            }
                            else if (messageType[1] == 0x03)
                            {
                                if (messageType[2] == 0x01)
                                {
                                    callback.Invoke(this, true);
                                }
                                else
                                {
                                    callback.Invoke(this, false);
                                    service.Dispose();
                                }
                            }
                        };
                    }

                    // Define auth secret key
                    byte[] hash = new SHA256Managed().ComputeHash(Guid.NewGuid().ToByteArray());
                    _authKey = hash.Take(16).ToArray();

                    // Send key it to device
                    using (var stream = new MemoryStream()) {
                        stream.Write(new byte[] { 0x01, 0x08 }, 0, 2);
                        stream.Write(_authKey, 0, _authKey.Length);
                        manager.Write(characteristic, stream.ToArray());
                    }
                }
            }
        }