// TODO: find a proper place for this public static async Task <Application <TPrimitiveContent> > RegisterAsync(Connection.IConnectionConfiguration m2mConfig, IApplicationConfiguration appConfig, string inCse, Uri?caUri = null) { var con = new HttpConnection <TPrimitiveContent>(m2mConfig); var ae = await con.FindApplicationAsync(inCse, appConfig.AppId) ?? await con.RegisterApplicationAsync(appConfig); if (ae == null) { throw new InvalidOperationException("Unable to register application"); } if (con.ClientCertificate == null && caUri != null) { var csrUri = new Uri(caUri, "CertificateSigning"); var ccrUri = new Uri(caUri, "CertificateConfirm"); var tokenId = ae.Labels?.FirstOrDefault(l => l.StartsWith("token="))?.Substring("token=".Length); if (string.IsNullOrWhiteSpace(tokenId)) { throw new InvalidDataException("registered AE is missing 'token' label"); } using var privateKey = RSA.Create(4096); var certificateRequest = new CertificateRequest( $"CN={appConfig.AppId}", privateKey, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1); var sanBuilder = new SubjectAlternativeNameBuilder(); sanBuilder.AddDnsName(appConfig.AppId); sanBuilder.AddDnsName(ae.AE_ID); certificateRequest.CertificateExtensions.Add(sanBuilder.Build()); //Debug.WriteLine(certificateRequest.ToPemString()); var signingRequest = new CertificateSigningRequestBody { Request = new CertificateSigningRequest { Application = new Aetheros.OneM2M.Api.Registration.Application { AeId = ae.AE_ID, TokenId = tokenId }, X509Request = certificateRequest.ToPemString(), } }; using var handler = new HttpClientHandler { ServerCertificateCustomValidationCallback = (message, cert, chain, errors) => true }; using var client = new HttpClient(handler); CertificateSigningResponseBody signingResponse; using (var httpSigningResponse = await client.PostJsonAsync(csrUri, signingRequest)) signingResponse = await httpSigningResponse.DeserializeAsync <CertificateSigningResponseBody>(); if (signingResponse.Response == null) { throw new InvalidDataException("CertificateSigningResponse does not contain a response"); } if (signingResponse.Response.X509Certificate == null) { throw new InvalidDataException("CertificateSigningResponse does not contain a certificate"); } var signedCert = AosUtils.CreateX509Certificate(signingResponse.Response.X509Certificate); var confirmationRequest = new ConfirmationRequestBody { Request = new ConfirmationRequest { CertificateHash = Convert.ToBase64String(signedCert.GetCertHash(HashAlgorithmName.SHA256)), CertificateId = new CertificateId { Issuer = signedCert.Issuer, SerialNumber = int.Parse(signedCert.SerialNumber, System.Globalization.NumberStyles.HexNumber).ToString() }, TransactionId = signingResponse.Response.TransactionId, } }; using (var httpConfirmationResponse = await client.PostJsonAsync(ccrUri, confirmationRequest)) { var confirmationResponse = await httpConfirmationResponse.DeserializeAsync <ConfirmationResponseBody>(); if (confirmationResponse.Response == null) { throw new InvalidDataException("Invalid ConfirmationResponse"); } Debug.Assert(confirmationResponse.Response.Status == CertificateSigningStatus.Accepted); } using (var pubPrivEphemeral = signedCert.CopyWithPrivateKey(privateKey)) await File.WriteAllBytesAsync(m2mConfig.CertificateFilename, pubPrivEphemeral.Export(X509ContentType.Cert)); con = new HttpConnection <TPrimitiveContent>(m2mConfig.M2MUrl, signedCert); } return(new Application <TPrimitiveContent>(con, appConfig.AppId, ae.AE_ID, appConfig.UrlPrefix, appConfig.PoaUrl)); }