private async Task <RequestEnvelope.Types.PlatformRequest> GenerateSignature(RequestEnvelope requestEnvelope, GeoCoordinate currentLocation) { byte[] ticketBytes = requestEnvelope.AuthTicket != null?requestEnvelope.AuthTicket.ToByteArray() : requestEnvelope.AuthInfo.ToByteArray(); // Common device info var deviceInfo = new Signature.Types.DeviceInfo { DeviceId = _settings.DeviceId, DeviceBrand = _settings.DeviceBrand, DeviceModel = _settings.DeviceModel, DeviceModelBoot = _settings.DeviceModelBoot + "\0", HardwareManufacturer = _settings.HardwareManufacturer, HardwareModel = _settings.HardwareModel + "\0", FirmwareBrand = (_settings.DeviceModel == "iPhone" ? "iOS" : "iPhone OS"), FirmwareType = _settings.FirmwareType }; // Android if (_client.Platform == Platform.Android) { deviceInfo.AndroidBoardName = _settings.AndroidBoardName; deviceInfo.AndroidBootloader = _settings.AndroidBootloader; deviceInfo.DeviceModelIdentifier = _settings.DeviceModelIdentifier; deviceInfo.FirmwareTags = _settings.FirmwareTags; deviceInfo.FirmwareFingerprint = _settings.FirmwareFingerprint; } var sig = new Signature { SessionHash = _sessionHash, Unknown25 = _client.Unknown25, Timestamp = (ulong)Utils.GetTime(true), TimestampSinceStart = (ulong)(Utils.GetTime(true) - _client.StartTime), DeviceInfo = deviceInfo }; if (sig.TimestampSinceStart < 5000) { sig.TimestampSinceStart = (ulong)TRandomDevice.Next(5000, 8000); } var sen = new Signature.Types.SensorInfo() { LinearAccelerationX = TRandomDevice.Triangular(-3, 1, 0), LinearAccelerationY = TRandomDevice.Triangular(-2, 3, 0), LinearAccelerationZ = TRandomDevice.Triangular(-4, 2, 0), MagneticFieldX = TRandomDevice.Triangular(-50, 50, 0), MagneticFieldY = TRandomDevice.Triangular(-60, 50, -5), MagneticFieldZ = TRandomDevice.Triangular(-60, 40, -30), MagneticFieldAccuracy = TRandomDevice.Choice(new List <int>(new int[] { -1, 1, 1, 2, 2, 2, 2 })), AttitudePitch = TRandomDevice.Triangular(-1.5, 1.5, 0.2), AttitudeYaw = TRandomDevice.NextDouble(-3, 3), AttitudeRoll = TRandomDevice.Triangular(-2.8, 2.5, 0.25), RotationRateX = TRandomDevice.Triangular(-6, 4, 0), RotationRateY = TRandomDevice.Triangular(-5.5, 5, 0), RotationRateZ = TRandomDevice.Triangular(-5, 3, 0), GravityX = TRandomDevice.Triangular(-1, 1, 0.15), GravityY = TRandomDevice.Triangular(-1, 1, -.2), GravityZ = TRandomDevice.Triangular(-1, .7, -0.8), Status = 3 }; sen.TimestampSnapshot = (ulong)TRandomDevice.NextUInt((uint)(sig.TimestampSinceStart - 5000), (uint)(sig.TimestampSinceStart - 100)); sig.SensorInfo.Add(sen); var locationFix = new Signature.Types.LocationFix { Provider = TRandomDevice.Choice(new List <string>(new string[] { "network", "network", "network", "network", "fused" })), Latitude = (float)currentLocation.Latitude, Longitude = (float)currentLocation.Longitude, Altitude = (float)currentLocation.Altitude, ProviderStatus = 3, LocationType = 1 }; locationFix.TimestampSnapshot = (ulong)TRandomDevice.NextUInt((uint)(sig.TimestampSinceStart - 5000), (uint)(sig.TimestampSinceStart - 1000)); if (requestEnvelope.Accuracy >= 65) { locationFix.HorizontalAccuracy = TRandomDevice.Choice(new List <float>(new float[] { (float)requestEnvelope.Accuracy, 65, 65, TRandomDevice.Next(66, 80), 200 })); if (_client.Platform == Platform.Ios) { locationFix.VerticalAccuracy = (float)TRandomDevice.Triangular(35, 100, 65); } } else { locationFix.HorizontalAccuracy = (float)requestEnvelope.Accuracy; if (_client.Platform == Platform.Ios) { locationFix.VerticalAccuracy = requestEnvelope.Accuracy > 10 ? (float)TRandomDevice.Choice(new List <double>(new double[] { 24, 32, 48, 48, 64, 64, 96, 128 })) : (float)TRandomDevice.Choice(new List <double>(new double[] { 3, 4, 6, 6, 8, 12, 24 })); } } locationFix.HorizontalAccuracy = (float)Math.Round(locationFix.HorizontalAccuracy, GEOLOCATION_PRECISION); locationFix.VerticalAccuracy = (float)Math.Round(locationFix.VerticalAccuracy, GEOLOCATION_PRECISION); if (_client.Platform == Platform.Ios) { sig.ActivityStatus = new Signature.Types.ActivityStatus() { Stationary = true }; sig.ActivityStatus.Tilting |= TRandomDevice.NextDouble() > 0.50; if (TRandomDevice.NextDouble() > 0.95) { // No reading for roughly 1 in 20 updates locationFix.Course = -1; locationFix.Speed = -1; } else { // Course is iOS only. locationFix.Course = GetCourse(); // Speed is iOS only. locationFix.Speed = (float)TRandomDevice.Triangular(0.2, 4.25, 1); } } sig.LocationFix.Add(locationFix); string envelopString = JsonConvert.SerializeObject(requestEnvelope); var hashRequest = new HashRequestContent() { Latitude64 = BitConverter.DoubleToInt64Bits(currentLocation.Latitude), Longitude64 = BitConverter.DoubleToInt64Bits(currentLocation.Longitude), Accuracy64 = BitConverter.DoubleToInt64Bits(requestEnvelope.Accuracy), AuthTicket = ticketBytes, SessionData = _sessionHash.ToByteArray(), Requests = new List <byte[]>(), Timestamp = sig.Timestamp }; foreach (var request in requestEnvelope.Requests) { hashRequest.Requests.Add(request.ToByteArray()); } var res = await _client.Hasher.RequestHashesAsync(hashRequest).ConfigureAwait(false); foreach (var item in res.RequestHashes) { sig.RequestHash.Add(((ulong)item)); } sig.LocationHash1 = (int)res.LocationAuthHash; sig.LocationHash2 = (int)res.LocationHash; var encryptedSignature = new RequestEnvelope.Types.PlatformRequest { Type = PlatformRequestType.SendEncryptedSignature, RequestMessage = new SendEncryptedSignatureRequest { EncryptedSignature = ByteString.CopyFrom(_client.Cryptor.Encrypt(sig.ToByteArray(), (uint)_client.StartTime)) }.ToByteString() }; return(encryptedSignature); }