Example #1
0
        public static async Task <IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Function, "post", Route = null)] HttpRequest req,
            ILogger log,
            ExecutionContext context)
        {
            log.LogInformation("Certificate trigger function processed a request.");

            try
            {
                await ReadAppSettings(context, log);

                string requestBody          = await new StreamReader(req.Body).ReadToEndAsync();
                Certificate_Request request = JsonConvert.DeserializeObject <Certificate_Request>(requestBody);

                // Validate payload
                if (string.IsNullOrEmpty(request.RegistrationId) || string.IsNullOrEmpty(request.Csr))
                {
                    return(new BadRequestResult());
                }

                // Check if the device is authorized to request a certificate
                bool isAuthorized = CheckIfAuthorized(request.RegistrationId);

                if (isAuthorized)
                {
                    log.LogInformation($"{request.RegistrationId} is authorized.");

                    Pkcs10CertificationRequest decodedCsr = null;
                    RsaKeyParameters           publicKey  = null;
                    CertificationRequestInfo   info       = null;

                    // Get the signing certificate from a location
                    X509Certificate serverCertificate = ReadCertificate(cert, location, log);

                    if (serverCertificate == null)
                    {
                        throw new System.Exception("ReadCertificate() was unable to retrieve the signing certificate.");
                    }

                    // Get signing cert private key from a location.
                    AsymmetricKeyParameter serverPrivateKey = ReadPrivateKey(key, location, log);

                    if (serverPrivateKey == null)
                    {
                        throw new System.Exception("ReadPrivateKey() was unable to retrieve the private key.");
                    }

                    byte[] csr = Convert.FromBase64String(request.Csr);

                    // Decode DER
                    decodedCsr = new Pkcs10CertificationRequest(csr);
                    info       = decodedCsr.GetCertificationRequestInfo();
                    SubjectPublicKeyInfo publicKeyInfo = info.SubjectPublicKeyInfo;

                    RsaPublicKeyStructure publicKeyStructure = RsaPublicKeyStructure.GetInstance(publicKeyInfo.ParsePublicKey());

                    publicKey = new RsaKeyParameters(false, publicKeyStructure.Modulus, publicKeyStructure.PublicExponent);

                    bool certIsOK = decodedCsr.Verify(publicKey);

                    // Create the device certificate
                    X509V3CertificateGenerator generator = new X509V3CertificateGenerator();

                    generator.SetSerialNumber(BigInteger.ProbablePrime(120, new Random()));
                    generator.SetIssuerDN(serverCertificate.SubjectDN);
                    generator.SetNotBefore(DateTime.Now);
                    generator.SetNotAfter(DateTime.Now.AddYears(certificateLifespanInYears));
                    generator.SetSubjectDN(info.Subject);
                    generator.SetPublicKey(publicKey);
                    generator.SetSignatureAlgorithm("SHA512withRSA");
                    generator.AddExtension(X509Extensions.AuthorityKeyIdentifier, false, new AuthorityKeyIdentifierStructure(serverCertificate));
                    generator.AddExtension(X509Extensions.SubjectKeyIdentifier, false, new SubjectKeyIdentifierStructure(publicKey));

                    // Generate the device certificate
                    var deviceCert = generator.Generate(serverPrivateKey);

                    // Convert to DER
                    byte[] encoded = deviceCert.GetEncoded();

                    // Convert byte array to Base64 string
                    string encodedString = Convert.ToBase64String(encoded);

                    Certificate_Response responseMessage = new Certificate_Response
                    {
                        Certificate = encodedString
                    };

                    log.LogInformation($"Certificate issued for: {info.Subject}");

                    return(new OkObjectResult(responseMessage));
                }
                else
                {
                    log.LogError($"{request.RegistrationId} is NOT authorized.");

                    return(new UnauthorizedResult());
                }
            }
            catch (Exception ex)
            {
                log.LogInformation(ex.Message);
            }

            return(new BadRequestResult());
        }
Example #2
0
        /// <summary>
        /// Generates and sends a CSR to Xboot.Server REST endpoint.
        /// </summary>
        /// <param name="registrationId"></param>
        /// <param name="name"></param>
        /// <returns>Pfx in DER-encoded byte array</returns>
        public byte[] GetDeviceCertificate(string registrationId, X500DistinguishedName name)
        {
            byte[] pfx = null;

            var req = new CertificateRequest(name, _rsa, HashAlgorithmName.SHA512,
                                             RSASignaturePadding.Pss);

            // Returns a DER-encoded PKCS#10 CSR
            var csr = req.CreateSigningRequest();

            Certificate_Request request = new Certificate_Request
            {
                RegistrationId = registrationId,
                Csr            = Convert.ToBase64String(csr)
            };

            var json = JsonConvert.SerializeObject(request);

            var client = new HttpClient();

            client.DefaultRequestHeaders.Accept.Clear();
            client.DefaultRequestHeaders.Accept.Add(
                new MediaTypeWithQualityHeaderValue("application/json"));

            var buffer      = System.Text.Encoding.UTF8.GetBytes(json);
            var byteContent = new ByteArrayContent(buffer);

            try
            {
                var response = client.PostAsync(_xBootUri, byteContent).Result;

                if (response.IsSuccessStatusCode)
                {
                    // Get the response
                    var jsonString = response.Content.ReadAsStringAsync().Result;
                    var certString = JsonConvert.DeserializeObject <Certificate_Response>(jsonString);

                    byte[] certBytes = Convert.FromBase64String(certString.Certificate);

                    // Read in signed device certificate in DER format
                    X509Certificate2 cert = new X509Certificate2(certBytes);

                    // Add private key to cert
                    cert = cert.CopyWithPrivateKey(_rsa);

                    if (cert.HasPrivateKey)
                    {
                        // Combine certificate and private key into single pfx
                        // The IoT Device SDK needs both the certificate and the private key information.
                        // It expects to load a single PFX-formatted file containing all necessarily information.
                        pfx = cert.Export(X509ContentType.Pfx);
                    }
                }
                else
                {
                    throw new Exception(response.StatusCode.ToString());
                }
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }

            // Return certificate in DER-encoded byte array
            return(pfx);
        }