public static byte[] GetAndroidNonce(this DiagnosisSubmissionParameter submission) { var cleartext = GetAndroidNonceClearText(submission); var nonce = GetSha256(cleartext); return(nonce); }
public static byte[] CreateAndroidNonceV3(DiagnosisSubmissionParameter submission) { var cleartext = GetNonceClearTextV3(submission); var nonce = GetSha256(cleartext); return(nonce); }
private async Task <DiagnosisSubmissionParameter> CreateSubmissionAsync(IEnumerable <TemporaryExposureKey> temporaryExposureKeys, PositiveDiagnosisState pendingDiagnosis) { loggerService.StartMethod(); // Filter Temporary exposure keys var filteredTemporaryExposureKeys = ExposureNotificationService.FliterTemporaryExposureKeys(temporaryExposureKeys); // Create the network keys var keys = filteredTemporaryExposureKeys.Select(k => new DiagnosisSubmissionParameter.Key { KeyData = Convert.ToBase64String(k.Key), RollingStartNumber = (uint)(k.RollingStart - DateTime.UnixEpoch).TotalMinutes / 10, RollingPeriod = (uint)(k.RollingDuration.TotalMinutes / 10), TransmissionRisk = (int)k.TransmissionRiskLevel }); var beforeKey = Utils.SerializeToJson(temporaryExposureKeys.ToList()); var afterKey = Utils.SerializeToJson(keys.ToList()); Debug.WriteLine($"C19R {beforeKey}"); Debug.WriteLine($"C19R {afterKey}"); if (keys.Count() == 0) { loggerService.Error($"Temporary exposure keys is empty."); loggerService.EndMethod(); throw new InvalidDataException(); } // Generate Padding var padding = GetPadding(); loggerService.Info($"userData is {(userData == null ? "" : "not ")}null or empty."); // Create the submission var submission = new DiagnosisSubmissionParameter() { UserUuid = userData.UserUuid, Keys = keys.ToArray(), Regions = AppSettings.Instance.SupportedRegions, Platform = DeviceInfo.Platform.ToString().ToLowerInvariant(), DeviceVerificationPayload = null, AppPackageName = AppInfo.PackageName, VerificationPayload = pendingDiagnosis.DiagnosisUid, Padding = padding }; // See if we can add the device verification if (DependencyService.Get <IDeviceVerifier>() is IDeviceVerifier verifier) { submission.DeviceVerificationPayload = await verifier?.VerifyAsync(submission); } loggerService.Info($"UserUuid is {(string.IsNullOrEmpty(submission.UserUuid) ? "null or empty" : "set")}."); loggerService.Info($"DeviceVerificationPayload is {(string.IsNullOrEmpty(submission.DeviceVerificationPayload) ? "null or empty" : "set")}."); loggerService.Info($"VerificationPayload is {(string.IsNullOrEmpty(submission.VerificationPayload) ? "null or empty" : "set")}."); loggerService.EndMethod(); return(submission); }
public async Task <HttpStatusCode> PutSelfExposureKeysAsync(DiagnosisSubmissionParameter request) { loggerService.StartMethod(); try { await serverConfigurationRepository.LoadAsync(); var diagnosisKeyRegisterApiUrls = serverConfigurationRepository.DiagnosisKeyRegisterApiUrls; if (diagnosisKeyRegisterApiUrls.Count() == 0) { loggerService.Error("DiagnosisKeyRegisterApiUrls count 0"); throw new InvalidOperationException("DiagnosisKeyRegisterApiUrls count 0"); } else if (diagnosisKeyRegisterApiUrls.Count() > 1) { loggerService.Warning("Multi DiagnosisKeyRegisterApiUrl are detected."); } var url = diagnosisKeyRegisterApiUrls.First(); var content = new StringContent(JsonConvert.SerializeObject(request), Encoding.UTF8, "application/json"); return(await PutAsync(url, content)); } finally { loggerService.EndMethod(); } }
/// <summary> /// Validation Android /// </summary> /// <param name="param">subumission parameter</param> /// <returns>True when successful.</returns> public async Task <bool> ValidationAndroid(DiagnosisSubmissionParameter param) { try { var token = new JwtSecurityToken(param.DeviceVerificationPayload); // TODO: Token Validate // request var payload = new AndroidPayload() { SignedAttestation = param.DeviceVerificationPayload }; var content = new StringContent(JsonConvert.SerializeObject(payload)); content.Headers.ContentType.MediaType = "application/json"; var request = new HttpRequestMessage(HttpMethod.Post, UrlAndroid + AndroidBearerToken); // response var response = await ClientAndroid.SendAsync(request); var responseBody = await response.Content.ReadAsStringAsync(); var result = JsonConvert.DeserializeObject <AndroidResponse>(responseBody); return(result.IsValidSignature); } catch (Exception) { } return(false); }
public async Task RunAsyncMethod(bool isValid, bool isValidDevice, string submissionNumber, string userUuid) { // preparation var config = new Mock <IConfiguration>(); config.Setup(_ => _["SupportRegions"]).Returns("Region1,Region2"); var diagnosisRepo = new Mock <IDiagnosisRepository>(); diagnosisRepo.Setup(_ => _.SubmitDiagnosisAsync(It.IsAny <string>(), It.IsAny <DateTimeOffset>(), It.IsAny <string>(), It.IsAny <TemporaryExposureKeyModel[]>())) .Returns(Task.CompletedTask); var tekRepo = new Mock <ITemporaryExposureKeyRepository>(); var validation = new Mock <IValidationUserService>(); var validationResult = new IValidationUserService.ValidateResult() { IsValid = isValid }; validation.Setup(_ => _.ValidateAsync(It.IsAny <HttpRequest>(), It.IsAny <IUser>())).ReturnsAsync(validationResult); var deviceCheck = new Mock <IDeviceValidationService>(); deviceCheck.Setup(_ => _.Validation(It.IsAny <DiagnosisSubmissionParameter>())).ReturnsAsync(isValidDevice); var logger = new Mock.LoggerMock <Covid19Radar.Api.DiagnosisApi>(); var diagnosisApi = new DiagnosisApi(config.Object, diagnosisRepo.Object, tekRepo.Object, validation.Object, deviceCheck.Object, logger); var context = new Mock <HttpContext>(); var bodyJson = new DiagnosisSubmissionParameter() { SubmissionNumber = submissionNumber, UserUuid = userUuid, Keys = new DiagnosisSubmissionParameter.Key[] { new DiagnosisSubmissionParameter.Key() { KeyData = "", RollingPeriod = 1, RollingStartNumber = 1 } } }; var bodyString = Newtonsoft.Json.JsonConvert.SerializeObject(bodyJson); using var stream = new System.IO.MemoryStream(); using (var writer = new System.IO.StreamWriter(stream, leaveOpen: true)) { await writer.WriteAsync(bodyString); await writer.FlushAsync(); } stream.Seek(0, System.IO.SeekOrigin.Begin); context.Setup(_ => _.Request.Body).Returns(stream); // action await diagnosisApi.RunAsync(context.Object.Request); // assert }
public void PropertiesTest() { // preparation var model = new DiagnosisSubmissionParameter(); // model property access Helper.ModelTestHelper.PropetiesTest(model); }
Task <HttpStatusCode> IHttpDataService.PutSelfExposureKeysAsync(DiagnosisSubmissionParameter request) { return(Task.Factory.StartNew <HttpStatusCode>(() => { Debug.WriteLine("HttpDataServiceMock::PutSelfExposureKeysAsync called"); return HttpStatusCode.OK; })); }
public async Task <HttpStatusCode> PutSelfExposureKeysAsync(DiagnosisSubmissionParameter request) { var url = $"{AppSettings.Instance.ApiUrlBase.TrimEnd('/')}/diagnosis"; var content = new StringContent(Utils.SerializeToJson(request), Encoding.UTF8, "application/json"); HttpStatusCode status = await PutAsync(url, content); return(status); }
/// <summary> /// Validation Android /// </summary> /// <param name="param">subumission parameter</param> /// <returns>True when successful.</returns> public bool Validation(DiagnosisSubmissionParameter param, byte[] expectedNonce, DateTimeOffset requestTime, AuthorizedAppInformation app) { var claims = ParsePayload(param.DeviceVerificationPayload); // Validate the nonce if (Convert.ToBase64String(claims.Nonce) != Convert.ToBase64String(expectedNonce)) { return(false); } // Validate time interval var now = requestTime.ToUnixTimeMilliseconds(); if (app.SafetyNetPastTimeSeconds > 0) { var minTime = now - (app.SafetyNetPastTimeSeconds * 1000); if (claims.TimestampMilliseconds < minTime) { return(false); } } if (app.SafetyNetFutureTimeSeconds > 0) { var minTime = now + (app.SafetyNetFutureTimeSeconds * 1000); if (claims.TimestampMilliseconds > minTime) { return(false); } } // Validate certificate if (app.SafetyNetApkDigestSha256?.Length > 0) { var apkSha = Convert.ToBase64String(claims.ApkCertificateDigestSha256); if (!app.SafetyNetApkDigestSha256.Contains(apkSha)) { return(false); } } // Validate integrity if (app.SafetyNetCtsProfileMatch) { if (!claims.CtsProfileMatch) { return(false); } } if (app.SafetyNetBasicIntegrity) { if (!claims.BasicIntegrity) { return(false); } } return(true); }
public async Task <HttpStatusCode> PutSelfExposureKeysAsync(DiagnosisSubmissionParameter request) { loggerService.StartMethod(); var url = $"{AppSettings.Instance.ApiUrlBase.TrimEnd('/')}/v2/diagnosis"; var content = new StringContent(JsonConvert.SerializeObject(request), Encoding.UTF8, "application/json"); HttpStatusCode status = await PutAsync(url, content); loggerService.EndMethod(); return(status); }
public async Task <bool> Validation(DiagnosisSubmissionParameter param, DateTimeOffset requestTime) { var app = await AuthApp.GetAsync(param.Platform); return(param.Platform switch { "android" => await Android.Validation(param, param.GetAndroidNonce(), requestTime, app), "ios" => await Apple.Validation(param, requestTime, app), _ => false, });
private async Task <DiagnosisSubmissionParameter> CreateSubmissionAsync(IEnumerable <TemporaryExposureKey> temporaryExposureKeys, PositiveDiagnosisState pendingDiagnosis) { // Create the network keys var keys = temporaryExposureKeys.Select(k => new DiagnosisSubmissionParameter.Key { KeyData = Convert.ToBase64String(k.Key), RollingStartNumber = (uint)(k.RollingStart - DateTime.UnixEpoch).TotalMinutes / 10, RollingPeriod = (uint)(k.RollingDuration.TotalMinutes / 10), TransmissionRisk = (int)k.TransmissionRiskLevel }); var beforeKey = Utils.SerializeToJson(temporaryExposureKeys.ToList()); var afterKey = Utils.SerializeToJson(keys.ToList()); Debug.WriteLine($"C19R {beforeKey}"); Debug.WriteLine($"C19R {afterKey}"); foreach (var key in keys) { if (!key.IsValid()) { Debug.WriteLine($"C19R Invalid Key Expcetion"); throw new InvalidDataException(); } } if (keys.ToArray() == null) { throw new InvalidDataException(); } // Generate Padding var padding = GetPadding(); // Create the submission var submission = new DiagnosisSubmissionParameter() { UserUuid = userData.UserUuid, Keys = keys.ToArray(), Regions = AppSettings.Instance.SupportedRegions, Platform = DeviceInfo.Platform.ToString().ToLowerInvariant(), DeviceVerificationPayload = null, AppPackageName = AppInfo.PackageName, VerificationPayload = pendingDiagnosis.DiagnosisUid, Padding = padding }; // See if we can add the device verification if (DependencyService.Get <IDeviceVerifier>() is IDeviceVerifier verifier) { submission.DeviceVerificationPayload = await verifier?.VerifyAsync(submission); } return(submission); }
// Put /diagnosis - upload self diagnosys file public async Task PutSelfExposureKeysAsync(DiagnosisSubmissionParameter request) { var url = $"{AppSettings.Instance.ApiUrlBase.TrimEnd('/')}/diagnosis"; var content = new StringContent(Utils.SerializeToJson(request), Encoding.UTF8, "application/json"); var result = await PutAsync(url, content); if (result != null) { System.Console.WriteLine(Utils.SerializeToJson(result)); } }
public async Task <bool> Validation(DiagnosisSubmissionParameter param) { switch (param.Platform) { case "android": return(await ValidationAndroid(param)); case "ios": return(await ValidationApple(param)); } return(false); }
private async Task <DiagnosisSubmissionParameter> CreateSubmissionAsync(IEnumerable <TemporaryExposureKey> temporaryExposureKeys, string positiveDiagnosis) { var loggerService = LoggerService; loggerService.StartMethod(); // Filter Temporary exposure keys var filteredTemporaryExposureKeys = ExposureNotificationService.FliterTemporaryExposureKeys(temporaryExposureKeys); // Create the network keys var keys = filteredTemporaryExposureKeys.Select(k => new DiagnosisSubmissionParameter.Key { KeyData = Convert.ToBase64String(k.Key), RollingStartNumber = (uint)(k.RollingStart - DateTime.UnixEpoch).TotalMinutes / 10, RollingPeriod = (uint)(k.RollingDuration.TotalMinutes / 10), }); var beforeKey = JsonConvert.SerializeObject(temporaryExposureKeys.ToList()); var afterKey = JsonConvert.SerializeObject(keys.ToList()); Debug.WriteLine($"C19R {beforeKey}"); Debug.WriteLine($"C19R {afterKey}"); if (keys.Count() == 0) { loggerService.Error($"Temporary exposure keys is empty."); loggerService.EndMethod(); throw new InvalidDataException(); } // Generate Padding var padding = GetPadding(); // Create the submission var submission = new DiagnosisSubmissionParameter() { Keys = keys.ToArray(), Regions = AppSettings.Instance.SupportedRegions, Platform = DeviceInfo.Platform.ToString().ToLowerInvariant(), DeviceVerificationPayload = null, AppPackageName = AppInfo.PackageName, VerificationPayload = positiveDiagnosis, Padding = padding }; submission.DeviceVerificationPayload = await DeviceVerifier.VerifyAsync(submission); loggerService.Info($"DeviceVerificationPayload is {(string.IsNullOrEmpty(submission.DeviceVerificationPayload) ? "null or empty" : "set")}."); loggerService.Info($"VerificationPayload is {(string.IsNullOrEmpty(submission.VerificationPayload) ? "null or empty" : "set")}."); loggerService.EndMethod(); return(submission); }
public Task SubmitDiagnosisAsync(DiagnosisSubmissionParameter Parameter) { var item = new DiagnosisModel() { id = Parameter.UserUuid, PartitionKey = Parameter.SubmissionNumber, UserUuid = Parameter.UserUuid, Keys = Parameter.Keys }; return(_db.Diagnosis.UpsertItemAsync <DiagnosisModel>(item, new PartitionKey(item.PartitionKey))); }
/// <summary> /// Validation iOS /// </summary> /// <param name="param">subumission parameter</param> /// <returns>True when successful.</returns> /// <remarks> /// https://developer.apple.com/documentation/devicecheck/accessing_and_modifying_per-device_data /// </remarks> public async Task <bool> Validation(DiagnosisSubmissionParameter param, DateTimeOffset requestTime, AuthorizedAppInformation app) { var payload = new ApplePayload() { DeviceToken = param.DeviceVerificationPayload, Timestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds() }; var keysText = param.Keys .OrderBy(_ => _.KeyData) .Select(_ => _.KeyData) .Aggregate((a, b) => a + b); using (var sha = System.Security.Cryptography.SHA256.Create()) { var value = System.Text.Encoding.UTF8.GetBytes(param.AppPackageName + keysText + string.Join(',', param.Regions)); payload.TransactionId = Convert.ToBase64String(sha.ComputeHash(value)); } var jwt = GenerateClientSecretJWT(requestTime, app.DeviceCheckKeyId, app.DeviceCheckTeamId, app.DeviceCheckPrivateKey); var content = new StringContent(JsonConvert.SerializeObject(payload)); var request = new HttpRequestMessage(HttpMethod.Post, UrlApple); request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", jwt); var response = await ClientApple.SendAsync(request); //switch (response.StatusCode) //{ // // 200 OK: The transaction was successful // // 200 Bit State Not Found: The bit state wasn't found // case System.Net.HttpStatusCode.OK: // if (response.ReasonPhrase == "OK") return true; // break; // // // default: // break; //} if (response.StatusCode != System.Net.HttpStatusCode.OK) { return(false); } return(true); }
public void AndroidClearTextTestV3_NoSymptom() { var platform = "Android"; var dummyDiagnosisKeyDataList = new[] { CreateDiagnosisKey("KeyData1", 10000, 140, 1), CreateDiagnosisKey("KeyData2", 20000, 141, 1), CreateDiagnosisKey("KeyData3", 30000, 142, 1), CreateDiagnosisKey("KeyData4", 40000, 143, 1), CreateDiagnosisKey("KeyData5", 50000, 70, 1), }; var dummyRegions = new string[] { "440", "441", }; var dummySymptomOnsetDate = "2021-12-19T19:02:00.000+09:00"; var dummyDeviceVerificationPayload = "DeviceVerificationPayload THIS STRING IS MEANINGLESS"; var dummyAppPackageName = "jp.go.mhlw.cocoa.unit_test"; var dummyVerificationPayload = "VerificationPayload THIS STRING IS MEANINGLESS"; // This value will not affect any result. var dummyPadding = new Random().Next().ToString(); var submissionParameter = new DiagnosisSubmissionParameter() { HasSymptom = false, Platform = platform, Regions = dummyRegions, OnsetOfSymptomOrTestDate = dummySymptomOnsetDate, Keys = dummyDiagnosisKeyDataList, DeviceVerificationPayload = dummyDeviceVerificationPayload, AppPackageName = dummyAppPackageName, VerificationPayload = dummyVerificationPayload, Padding = dummyPadding, }; string clearText = DeviceVerifierUtils.GetNonceClearTextV3(submissionParameter); Assert.Equal( EXPECTED_CLEAR_TEXT_V3_NOSYMPTOM, clearText ); }
private async Task <DiagnosisSubmissionParameter> CreateSubmissionAsync( DateTime symptomOnsetDate, IList <TemporaryExposureKey> temporaryExposureKeys, string processNumber, string idempotencyKey ) { _loggerService.StartMethod(); // Create the network keys var keys = temporaryExposureKeys.Select(k => new DiagnosisSubmissionParameter.Key { KeyData = Convert.ToBase64String(k.KeyData), RollingStartNumber = (uint)k.RollingStartIntervalNumber, RollingPeriod = (uint)k.RollingPeriod, ReportType = (uint)k.ReportType, }); // Generate Padding var padding = GetPadding(); // Create the submission var submission = new DiagnosisSubmissionParameter() { SymptomOnsetDate = symptomOnsetDate.ToString(AppConstants.FORMAT_TIMESTAMP), Keys = keys.ToArray(), Regions = AppSettings.Instance.SupportedRegions, Platform = DeviceInfo.Platform.ToString().ToLowerInvariant(), DeviceVerificationPayload = null, AppPackageName = AppInfo.PackageName, VerificationPayload = processNumber, IdempotencyKey = idempotencyKey, Padding = padding }; submission.DeviceVerificationPayload = await _deviceVerifier.VerifyAsync(submission); _loggerService.Info($"DeviceVerificationPayload is {(string.IsNullOrEmpty(submission.DeviceVerificationPayload) ? "null or empty" : "set")}."); _loggerService.Info($"VerificationPayload is {(string.IsNullOrEmpty(submission.VerificationPayload) ? "null or empty" : "set")}."); _loggerService.EndMethod(); return(submission); }
public async Task <bool> Validation(DiagnosisSubmissionParameter param, DateTimeOffset requestTime) { var app = await AuthApp.GetAsync(param.Platform); // unsupported if (app == null) { return(false); } if (!app.DeviceValidationEnabled) { return(true); } return(param.Platform switch { "android" => Android.Validation(param, param.GetAndroidNonce(), requestTime, app), "ios" => await Apple.Validation(param, requestTime, app), _ => false, });
Task <HttpStatusCode> IHttpDataService.PutSelfExposureKeysAsync(DiagnosisSubmissionParameter request) { var code = HttpStatusCode.OK; // default. for PutSelfExposureKeys NG var dataType = mockCommonUtils.GetDiagnosisDataType(); if (dataType >= 100) // HttpStatusCode >=100 by RFC2616#section-10 { code = (HttpStatusCode)dataType; } else { switch (dataType) { case 1: code = HttpStatusCode.NoContent; // for Successful PutSelfExposureKeys break; } } Debug.WriteLine("HttpDataServiceMock::PutSelfExposureKeysAsync called"); return(Task.FromResult(code)); }
public void ToModelTest(string keyData, int period, int expectedPeriod, int start) { // preparation var keyDataBytes = Encoding.UTF8.GetBytes(keyData); var keyDataBase64 = Convert.ToBase64String(keyDataBytes); var model = new DiagnosisSubmissionParameter(); model.Keys = new DiagnosisSubmissionParameter.Key[] { new DiagnosisSubmissionParameter.Key() { KeyData = keyDataBase64, RollingPeriod = (uint)period, RollingStartNumber = (uint)start, TransmissionRisk = 0 } }; var timestamp = (ulong)DateTimeOffset.UtcNow.ToUnixTimeSeconds(); // action var result = model.Keys.Select(_ => _.ToModel(model, timestamp)); var item = result.First(); // assert CollectionAssert.AreEqual(keyDataBytes, item.KeyData); Assert.AreEqual(expectedPeriod, item.RollingPeriod); Assert.AreEqual(start, item.RollingStartIntervalNumber); }
private static byte[] GetNonce(DiagnosisSubmissionParameter submission) { var cleartext = GetNonceClearText(submission); var nonce = GetSha256(cleartext); return(nonce);
private async Task<DiagnosisSubmissionParameter> CreateSubmissionAsync( bool hasSymptom, DateTime symptomOnsetDate, IList<TemporaryExposureKey> temporaryExposureKeys, string processNumber, string idempotencyKey ) { _loggerService.StartMethod(); // Create the network keys var keys = temporaryExposureKeys.Select(k => new DiagnosisSubmissionParameter.Key { KeyData = Convert.ToBase64String(k.KeyData), RollingStartNumber = (uint)k.RollingStartIntervalNumber, RollingPeriod = (uint)k.RollingPeriod, ReportType = (uint)k.ReportType, }); // Generate Padding var padding = GetPadding(); // Create the submission var submission = new DiagnosisSubmissionParameter() { HasSymptom = hasSymptom, OnsetOfSymptomOrTestDate = symptomOnsetDate.ToString(AppConstants.FORMAT_TIMESTAMP), Keys = keys.ToArray(), Regions = AppSettings.Instance.SupportedRegions, Platform = DeviceInfo.Platform.ToString().ToLowerInvariant(), DeviceVerificationPayload = null, AppPackageName = AppInfo.PackageName, VerificationPayload = processNumber, IdempotencyKey = idempotencyKey, Padding = padding }; // Create device verification payload var tries = 0; var delay = 4 * 1000; while (true) { var deviceVerificationPayload = await _deviceVerifier.VerifyAsync(submission); if (!_deviceVerifier.IsErrorPayload(deviceVerificationPayload)) { _loggerService.Info("Payload creation successful."); submission.DeviceVerificationPayload = deviceVerificationPayload; break; } else if (tries >= 3) { _loggerService.Error("Payload creation failed all."); throw new DiagnosisKeyRegisterException(DiagnosisKeyRegisterException.Codes.FailedCreatePayload); } _loggerService.Warning($"Payload creation failed. {tries + 1} time(s)."); _loggerService.Info($"delay {delay} msec"); await Task.Delay(delay); delay *= 2; tries++; } _loggerService.Info($"DeviceVerificationPayload is {(string.IsNullOrEmpty(submission.DeviceVerificationPayload) ? "null or empty" : "set")}."); _loggerService.Info($"VerificationPayload is {(string.IsNullOrEmpty(submission.VerificationPayload) ? "null or empty" : "set")}."); _loggerService.EndMethod(); return submission; }
public Task <bool> Validation(DiagnosisSubmissionParameter param, DateTimeOffset requestTime) { return(Task.FromResult(true)); }
public static string GetNonceClearTextV3(DiagnosisSubmissionParameter submission) { return(string.Join("|", submission.SymptomOnsetDate, submission.AppPackageName, GetKeyString(submission.Keys), GetRegionString(submission.Regions), submission.VerificationPayload));
/// <summary> /// Validation iOS /// </summary> /// <param name="param">subumission parameter</param> /// <returns>True when successful.</returns> /// <remarks> /// https://developer.apple.com/documentation/devicecheck/accessing_and_modifying_per-device_data /// </remarks> public async Task <bool> Validation(DiagnosisSubmissionParameter param, DateTimeOffset requestTime, AuthorizedAppInformation app) { var payload = new ApplePayload() { DeviceToken = param.DeviceVerificationPayload, Timestamp = requestTime.ToUnixTimeMilliseconds() }; var keysText = string.Empty; if (param is V1DiagnosisSubmissionParameter) { keysText = (param as V1DiagnosisSubmissionParameter).Keys .OrderBy(_ => _.KeyData) .Select(_ => _.KeyData) .Aggregate((a, b) => a + b); } else { keysText = param.Keys .OrderBy(_ => _.KeyData) .Select(_ => _.KeyData) .Aggregate((a, b) => a + b); } using (var sha = System.Security.Cryptography.SHA256.Create()) { var value = System.Text.Encoding.UTF8.GetBytes(param.AppPackageName + keysText + string.Join(',', param.Regions)); payload.TransactionId = Convert.ToBase64String(sha.ComputeHash(value)); } Logger.LogInformation($"{nameof(Validation)} DeviceCheckKeyId:{app.DeviceCheckKeyId} DeviceCheckTeamId:{app.DeviceCheckTeamId} DeviceCheckPrivateKey:{app.DeviceCheckPrivateKey}"); var jwt = GenerateClientSecretJWT(requestTime, app.DeviceCheckKeyId, app.DeviceCheckTeamId, app.DeviceCheckPrivateKey); var payloadJson = JsonConvert.SerializeObject(payload); Logger.LogInformation($"{nameof(Validation)} payload:{payloadJson} "); var request = new HttpRequestMessage(HttpMethod.Post, UrlApple); request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", jwt); request.Content = new StringContent(payloadJson, Encoding.UTF8, "application/json"); try { var response = await ClientApple.SendAsync(request); if (!response.IsSuccessStatusCode) { var responseBody = await response.Content.ReadAsStringAsync(); Logger.LogWarning($"POST {UrlApple} {response.StatusCode} {response.ReasonPhrase} {responseBody}"); } //switch (response.StatusCode) //{ // // 200 OK: The transaction was successful // // 200 Bit State Not Found: The bit state wasn't found // case System.Net.HttpStatusCode.OK: // if (response.ReasonPhrase == "OK") return true; // break; // // // default: // break; //} if (response.StatusCode != System.Net.HttpStatusCode.OK) { return(false); } return(true); } catch (Exception ex) { Logger.LogError(ex, $"{nameof(Validation)}"); throw; } }
public static string GetNonceClearTextV3(DiagnosisSubmissionParameter submission) { string hasSymptom = submission.HasSymptom ? "HasSymptom" : "NoSymptom"; return(string.Join("|", submission.AppPackageName, submission.OnsetOfSymptomOrTestDate, hasSymptom, GetKeyString(submission.Keys), GetRegionString(submission.Regions), submission.VerificationPayload));
static string GetNonceClearText(DiagnosisSubmissionParameter submission) => string.Join("|", submission.AppPackageName, GetKeyString(submission.Keys), GetRegionString(submission.Regions), submission.VerificationPayload);