/// <summary> /// Sends a contact request to the specified Bluetooth device. /// </summary> /// <param name="device">The device to send the request to.</param> /// <param name="myAddress">The local address to send to the device.</param> /// <returns>The Erebus address of the device if the request was accepted; otherwise null.</returns> public static ErebusAddress?RequestAddContact(RfcommDeviceService device, ErebusAddress myAddress) { Log.RecordEvent(typeof(BluetoothUtils), $"Attempting to add Bluetooth device '{device.ConnectionHostName.CanonicalName}' as a contact.", LogEntrySeverity.Info); try { var socket = new StreamSocket(); new Func <Task>(async() => { await socket.ConnectAsync(device.ConnectionHostName, RfcommAddContactService.AsString(), SocketProtectionLevel.BluetoothEncryptionWithAuthentication); })().Wait(); using (var r = new BinaryReader(socket.InputStream.AsStreamForRead())) using (var w = new BinaryWriter(socket.OutputStream.AsStreamForWrite())) { w.Write(myAddress); var addr = r.ReadErebusAddress(); var vkp = PlatformServiceProvider.Create("VerificationKeyProvider"); var local = vkp.CreatePrivateKey(); w.Write(local.Item2.Length); w.Write(local.Item2); vkp.AddKeyPair(addr, local.Item1, r.ReadBytes(r.ReadInt32())); Log.RecordEvent(typeof(BluetoothUtils), $"Successfully negotiated contact with {addr} via Bluetooth RFCOMM.", LogEntrySeverity.Info); return(addr); } } catch (Exception e) { Log.RecordEvent(typeof(BluetoothUtils), $"Exception adding contact: {e.Message}; assuming other user rejected request.", LogEntrySeverity.Error); return(null); } }
void retrieveKeys(ErebusAddress other) { var keys = PlatformServiceProvider.Create("VerificationKeyProvider").GetKeyPair(other); myKey = keys.Item1; otherKey = keys.Item2; }
bool core(ErebusAddress addr, bool request, Guid id, byte[] otherKey, Predicate <int> pinCheck) { var vkp = PlatformServiceProvider.Create("VerificationKeyProvider"); var k = vkp.CreatePrivateKey(); byte[] lp = k.Item2; using (var ewh = new EventWaitHandle(false, EventResetMode.ManualReset)) { bool l = false, r = false; lock (arh) arh[id] = a => { r = a; ewh.Set(); lock (arh) arh.Remove(id); }; if (request) { using (var kewh = new EventWaitHandle(false, EventResetMode.ManualReset)) { lock (hrh) hrh[id] = _k => { otherKey = _k; kewh.Set(); }; SendPacket(new ErebusEndpoint(addr, 1), new byte[] { 0 }.Concat(id.ToByteArray()).Concat(lp).ToArray()); kewh.WaitOne(); } } else { SendPacket(new ErebusEndpoint(addr, 1), new byte[] { 1 }.Concat(id.ToByteArray()).Concat(lp).ToArray()); } var hash = WinRTCrypto.HashAlgorithmProvider.OpenAlgorithm(HashAlgorithm.Sha512).HashData((request ? lp.Concat(otherKey) : otherKey.Concat(lp)).ToArray()); for (int i = 4; i < hash.Length; ++i) { hash[i % 4] ^= hash[i]; } l = pinCheck(BitConverter.ToInt32(hash, 0)); SendPacket(new ErebusEndpoint(addr, 1), new[] { (byte)(l ? 2 : 3) }.Concat(id.ToByteArray()).ToArray()); if (l) { ewh.WaitOne(); if (r) { vkp.AddKeyPair(addr, k.Item1, otherKey); return(true); } } } return(false); }
Task listenProcess() => Task.Run(async() => { var p = await RfcommServiceProvider.CreateAsync(BluetoothUtils.RfcommAddContactService); using (var l = new StreamSocketListener()) { l.ConnectionReceived += (sender, e) => { using (var r = new BinaryReader(e.Socket.InputStream.AsStreamForRead())) using (var w = new BinaryWriter(e.Socket.OutputStream.AsStreamForWrite())) { w.Write(true); r.ReadBoolean(); var _addr = r.ReadErebusAddress(); if (h(_addr, e.Socket.Information.RemoteHostName.DisplayName)) { w.Write(addr); var vkp = PlatformServiceProvider.Create("VerificationKeyProvider"); var local = vkp.CreatePrivateKey(); w.Write(local.Item2.Length); w.Write(local.Item2); vkp.AddKeyPair(addr, local.Item1, r.ReadBytes(r.ReadInt32())); Log.RecordEvent(this, $"Successfully negotiated contact with {_addr} via Bluetooth RFCOMM.", LogEntrySeverity.Info); } } }; await l.BindServiceNameAsync(BluetoothUtils.RfcommAddContactService.AsString(), SocketProtectionLevel.BluetoothEncryptionWithAuthentication); using (var w = new DataWriter()) { w.WriteByte(37); var name = "Erebus Contact Request Service"; w.WriteByte((byte)name.Length); w.UnicodeEncoding = UnicodeEncoding.Utf8; w.WriteString(name); p.SdpRawAttributes.Add(0x100, w.DetachBuffer()); } p.StartAdvertising(l); while (process) { await Task.Delay(10); } p.StopAdvertising(); } });