X509Certificate2 with Private Key signing data using SHA256withRSA












2















This is a bit related to the answer to X509Certificate2 from store with private key.



It seems that when I want to use SHA256withRSA I can't use service provider directly from the certificate's PrivateKey - I need to create new crypto service provider:



  var bytes = new byte { 0, 1, 2, 3 };

//_cert - X509Certificate2 with private key
//csp1 is of type I need, but it won't work
var csp1 = _cert.PrivateKey as RSACryptoServiceProvider;

var cspParameters = new CspParameters
{
KeyContainerName = csp1.CspKeyContainerInfo.KeyContainerName,
KeyNumber = csp1.CspKeyContainerInfo.KeyNumber == KeyNumber.Exchange ? 1 : 2,
};

var csp2 = new RSACryptoServiceProvider(cspParameters);

//I can't use csp1 here - will throw "CryptographicException : Invalid algorithm specified."
//I can use csp1 with "SHA1" though
var signature = csp2.SignData(bytes, CryptoConfig.MapNameToOID("SHA256"));


I've found some information about this here:



https://blogs.msdn.microsoft.com/shawnfa/2008/08/25/using-rsacryptoserviceprovider-for-rsa-sha256-signatures/



But the above solution is taken from comments section and I don't really understand why I need to jump through hoops to use one of the common algorithms. So what I want to ask is:




  • Why csp1 does not work with SHA256 exactly?

  • Is it correct to create the csp2 like I did?

  • Is there a better/newer way I can do it in .NET?


If needed the cert with private key can be generated as follows:



openssl req -x509 -sha256 -newkey rsa:2048 -keyout ./temp/key.key -out ./temp/crt.crt -days 10 –nodes
openssl pkcs12 -export -out .tempcert.pfx -inkey .tempkey.key –in .tempcrt.crt









share|improve this question



























    2















    This is a bit related to the answer to X509Certificate2 from store with private key.



    It seems that when I want to use SHA256withRSA I can't use service provider directly from the certificate's PrivateKey - I need to create new crypto service provider:



      var bytes = new byte { 0, 1, 2, 3 };

    //_cert - X509Certificate2 with private key
    //csp1 is of type I need, but it won't work
    var csp1 = _cert.PrivateKey as RSACryptoServiceProvider;

    var cspParameters = new CspParameters
    {
    KeyContainerName = csp1.CspKeyContainerInfo.KeyContainerName,
    KeyNumber = csp1.CspKeyContainerInfo.KeyNumber == KeyNumber.Exchange ? 1 : 2,
    };

    var csp2 = new RSACryptoServiceProvider(cspParameters);

    //I can't use csp1 here - will throw "CryptographicException : Invalid algorithm specified."
    //I can use csp1 with "SHA1" though
    var signature = csp2.SignData(bytes, CryptoConfig.MapNameToOID("SHA256"));


    I've found some information about this here:



    https://blogs.msdn.microsoft.com/shawnfa/2008/08/25/using-rsacryptoserviceprovider-for-rsa-sha256-signatures/



    But the above solution is taken from comments section and I don't really understand why I need to jump through hoops to use one of the common algorithms. So what I want to ask is:




    • Why csp1 does not work with SHA256 exactly?

    • Is it correct to create the csp2 like I did?

    • Is there a better/newer way I can do it in .NET?


    If needed the cert with private key can be generated as follows:



    openssl req -x509 -sha256 -newkey rsa:2048 -keyout ./temp/key.key -out ./temp/crt.crt -days 10 –nodes
    openssl pkcs12 -export -out .tempcert.pfx -inkey .tempkey.key –in .tempcrt.crt









    share|improve this question

























      2












      2








      2


      0






      This is a bit related to the answer to X509Certificate2 from store with private key.



      It seems that when I want to use SHA256withRSA I can't use service provider directly from the certificate's PrivateKey - I need to create new crypto service provider:



        var bytes = new byte { 0, 1, 2, 3 };

      //_cert - X509Certificate2 with private key
      //csp1 is of type I need, but it won't work
      var csp1 = _cert.PrivateKey as RSACryptoServiceProvider;

      var cspParameters = new CspParameters
      {
      KeyContainerName = csp1.CspKeyContainerInfo.KeyContainerName,
      KeyNumber = csp1.CspKeyContainerInfo.KeyNumber == KeyNumber.Exchange ? 1 : 2,
      };

      var csp2 = new RSACryptoServiceProvider(cspParameters);

      //I can't use csp1 here - will throw "CryptographicException : Invalid algorithm specified."
      //I can use csp1 with "SHA1" though
      var signature = csp2.SignData(bytes, CryptoConfig.MapNameToOID("SHA256"));


      I've found some information about this here:



      https://blogs.msdn.microsoft.com/shawnfa/2008/08/25/using-rsacryptoserviceprovider-for-rsa-sha256-signatures/



      But the above solution is taken from comments section and I don't really understand why I need to jump through hoops to use one of the common algorithms. So what I want to ask is:




      • Why csp1 does not work with SHA256 exactly?

      • Is it correct to create the csp2 like I did?

      • Is there a better/newer way I can do it in .NET?


      If needed the cert with private key can be generated as follows:



      openssl req -x509 -sha256 -newkey rsa:2048 -keyout ./temp/key.key -out ./temp/crt.crt -days 10 –nodes
      openssl pkcs12 -export -out .tempcert.pfx -inkey .tempkey.key –in .tempcrt.crt









      share|improve this question














      This is a bit related to the answer to X509Certificate2 from store with private key.



      It seems that when I want to use SHA256withRSA I can't use service provider directly from the certificate's PrivateKey - I need to create new crypto service provider:



        var bytes = new byte { 0, 1, 2, 3 };

      //_cert - X509Certificate2 with private key
      //csp1 is of type I need, but it won't work
      var csp1 = _cert.PrivateKey as RSACryptoServiceProvider;

      var cspParameters = new CspParameters
      {
      KeyContainerName = csp1.CspKeyContainerInfo.KeyContainerName,
      KeyNumber = csp1.CspKeyContainerInfo.KeyNumber == KeyNumber.Exchange ? 1 : 2,
      };

      var csp2 = new RSACryptoServiceProvider(cspParameters);

      //I can't use csp1 here - will throw "CryptographicException : Invalid algorithm specified."
      //I can use csp1 with "SHA1" though
      var signature = csp2.SignData(bytes, CryptoConfig.MapNameToOID("SHA256"));


      I've found some information about this here:



      https://blogs.msdn.microsoft.com/shawnfa/2008/08/25/using-rsacryptoserviceprovider-for-rsa-sha256-signatures/



      But the above solution is taken from comments section and I don't really understand why I need to jump through hoops to use one of the common algorithms. So what I want to ask is:




      • Why csp1 does not work with SHA256 exactly?

      • Is it correct to create the csp2 like I did?

      • Is there a better/newer way I can do it in .NET?


      If needed the cert with private key can be generated as follows:



      openssl req -x509 -sha256 -newkey rsa:2048 -keyout ./temp/key.key -out ./temp/crt.crt -days 10 –nodes
      openssl pkcs12 -export -out .tempcert.pfx -inkey .tempkey.key –in .tempcrt.crt






      c# .net cryptography






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked Nov 23 '18 at 15:12









      DevNewbDevNewb

      741617




      741617
























          1 Answer
          1






          active

          oldest

          votes


















          2





          +50









          It all depends on where your certificate is coming from. Like the MSDN comment says, if it's coming from Microsoft Base Cryptographic Provider, then it will not work with SHA256. This CSP came out with the first version of CryptoAPI back in 1996, and does not understand SHA256 because SHA256 was not around back then.



          The way to check and handle this gracefully would be:



          public byte SignData(RSACryptoServiceProvider csp, byte bytes)
          {
          byte sig = null;
          if ((csp.CspKeyContainerInfo.ProviderType == PROV_RSA_FULL || csp.CspKeyContainerInfo.ProviderType == PROV_RSA_SCHANNEL) && !csp.CspKeyContainerInfo.HardwareDevice)
          {
          var cspParameters = new CspParameters
          {
          KeyContainerName = csp.CspKeyContainerInfo.KeyContainerName,
          KeyNumber = csp.CspKeyContainerInfo.KeyNumber == KeyNumber.Exchange ? 1 : 2,
          };
          using (var csp2 = new RSACryptoServiceProvider(cspParameters))
          {
          sig = csp2.SignData(bytes, CryptoConfig.MapNameToOID("SHA256"));
          }
          }
          else {
          sig = csp.SignData(bytes, CryptoConfig.MapNameToOID("SHA256"));
          }
          return sig;
          }


          FYI the CryptoAPI is being deprecated in favor of Cryptography API: Next Generation. One way to do what you want with CNG in C# would be with System.Security.Cryptography.Cng:



          ...
          using (RSA rsa = new RSACng())
          {
          byte signature = rsa.SignData(message, hashAlgorithm, paddingMode);
          ...
          }





          share|improve this answer























            Your Answer






            StackExchange.ifUsing("editor", function () {
            StackExchange.using("externalEditor", function () {
            StackExchange.using("snippets", function () {
            StackExchange.snippets.init();
            });
            });
            }, "code-snippets");

            StackExchange.ready(function() {
            var channelOptions = {
            tags: "".split(" "),
            id: "1"
            };
            initTagRenderer("".split(" "), "".split(" "), channelOptions);

            StackExchange.using("externalEditor", function() {
            // Have to fire editor after snippets, if snippets enabled
            if (StackExchange.settings.snippets.snippetsEnabled) {
            StackExchange.using("snippets", function() {
            createEditor();
            });
            }
            else {
            createEditor();
            }
            });

            function createEditor() {
            StackExchange.prepareEditor({
            heartbeatType: 'answer',
            autoActivateHeartbeat: false,
            convertImagesToLinks: true,
            noModals: true,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: 10,
            bindNavPrevention: true,
            postfix: "",
            imageUploader: {
            brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
            contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
            allowUrls: true
            },
            onDemand: true,
            discardSelector: ".discard-answer"
            ,immediatelyShowMarkdownHelp:true
            });


            }
            });














            draft saved

            draft discarded


















            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53449086%2fx509certificate2-with-private-key-signing-data-using-sha256withrsa%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown

























            1 Answer
            1






            active

            oldest

            votes








            1 Answer
            1






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes









            2





            +50









            It all depends on where your certificate is coming from. Like the MSDN comment says, if it's coming from Microsoft Base Cryptographic Provider, then it will not work with SHA256. This CSP came out with the first version of CryptoAPI back in 1996, and does not understand SHA256 because SHA256 was not around back then.



            The way to check and handle this gracefully would be:



            public byte SignData(RSACryptoServiceProvider csp, byte bytes)
            {
            byte sig = null;
            if ((csp.CspKeyContainerInfo.ProviderType == PROV_RSA_FULL || csp.CspKeyContainerInfo.ProviderType == PROV_RSA_SCHANNEL) && !csp.CspKeyContainerInfo.HardwareDevice)
            {
            var cspParameters = new CspParameters
            {
            KeyContainerName = csp.CspKeyContainerInfo.KeyContainerName,
            KeyNumber = csp.CspKeyContainerInfo.KeyNumber == KeyNumber.Exchange ? 1 : 2,
            };
            using (var csp2 = new RSACryptoServiceProvider(cspParameters))
            {
            sig = csp2.SignData(bytes, CryptoConfig.MapNameToOID("SHA256"));
            }
            }
            else {
            sig = csp.SignData(bytes, CryptoConfig.MapNameToOID("SHA256"));
            }
            return sig;
            }


            FYI the CryptoAPI is being deprecated in favor of Cryptography API: Next Generation. One way to do what you want with CNG in C# would be with System.Security.Cryptography.Cng:



            ...
            using (RSA rsa = new RSACng())
            {
            byte signature = rsa.SignData(message, hashAlgorithm, paddingMode);
            ...
            }





            share|improve this answer




























              2





              +50









              It all depends on where your certificate is coming from. Like the MSDN comment says, if it's coming from Microsoft Base Cryptographic Provider, then it will not work with SHA256. This CSP came out with the first version of CryptoAPI back in 1996, and does not understand SHA256 because SHA256 was not around back then.



              The way to check and handle this gracefully would be:



              public byte SignData(RSACryptoServiceProvider csp, byte bytes)
              {
              byte sig = null;
              if ((csp.CspKeyContainerInfo.ProviderType == PROV_RSA_FULL || csp.CspKeyContainerInfo.ProviderType == PROV_RSA_SCHANNEL) && !csp.CspKeyContainerInfo.HardwareDevice)
              {
              var cspParameters = new CspParameters
              {
              KeyContainerName = csp.CspKeyContainerInfo.KeyContainerName,
              KeyNumber = csp.CspKeyContainerInfo.KeyNumber == KeyNumber.Exchange ? 1 : 2,
              };
              using (var csp2 = new RSACryptoServiceProvider(cspParameters))
              {
              sig = csp2.SignData(bytes, CryptoConfig.MapNameToOID("SHA256"));
              }
              }
              else {
              sig = csp.SignData(bytes, CryptoConfig.MapNameToOID("SHA256"));
              }
              return sig;
              }


              FYI the CryptoAPI is being deprecated in favor of Cryptography API: Next Generation. One way to do what you want with CNG in C# would be with System.Security.Cryptography.Cng:



              ...
              using (RSA rsa = new RSACng())
              {
              byte signature = rsa.SignData(message, hashAlgorithm, paddingMode);
              ...
              }





              share|improve this answer


























                2





                +50







                2





                +50



                2




                +50





                It all depends on where your certificate is coming from. Like the MSDN comment says, if it's coming from Microsoft Base Cryptographic Provider, then it will not work with SHA256. This CSP came out with the first version of CryptoAPI back in 1996, and does not understand SHA256 because SHA256 was not around back then.



                The way to check and handle this gracefully would be:



                public byte SignData(RSACryptoServiceProvider csp, byte bytes)
                {
                byte sig = null;
                if ((csp.CspKeyContainerInfo.ProviderType == PROV_RSA_FULL || csp.CspKeyContainerInfo.ProviderType == PROV_RSA_SCHANNEL) && !csp.CspKeyContainerInfo.HardwareDevice)
                {
                var cspParameters = new CspParameters
                {
                KeyContainerName = csp.CspKeyContainerInfo.KeyContainerName,
                KeyNumber = csp.CspKeyContainerInfo.KeyNumber == KeyNumber.Exchange ? 1 : 2,
                };
                using (var csp2 = new RSACryptoServiceProvider(cspParameters))
                {
                sig = csp2.SignData(bytes, CryptoConfig.MapNameToOID("SHA256"));
                }
                }
                else {
                sig = csp.SignData(bytes, CryptoConfig.MapNameToOID("SHA256"));
                }
                return sig;
                }


                FYI the CryptoAPI is being deprecated in favor of Cryptography API: Next Generation. One way to do what you want with CNG in C# would be with System.Security.Cryptography.Cng:



                ...
                using (RSA rsa = new RSACng())
                {
                byte signature = rsa.SignData(message, hashAlgorithm, paddingMode);
                ...
                }





                share|improve this answer













                It all depends on where your certificate is coming from. Like the MSDN comment says, if it's coming from Microsoft Base Cryptographic Provider, then it will not work with SHA256. This CSP came out with the first version of CryptoAPI back in 1996, and does not understand SHA256 because SHA256 was not around back then.



                The way to check and handle this gracefully would be:



                public byte SignData(RSACryptoServiceProvider csp, byte bytes)
                {
                byte sig = null;
                if ((csp.CspKeyContainerInfo.ProviderType == PROV_RSA_FULL || csp.CspKeyContainerInfo.ProviderType == PROV_RSA_SCHANNEL) && !csp.CspKeyContainerInfo.HardwareDevice)
                {
                var cspParameters = new CspParameters
                {
                KeyContainerName = csp.CspKeyContainerInfo.KeyContainerName,
                KeyNumber = csp.CspKeyContainerInfo.KeyNumber == KeyNumber.Exchange ? 1 : 2,
                };
                using (var csp2 = new RSACryptoServiceProvider(cspParameters))
                {
                sig = csp2.SignData(bytes, CryptoConfig.MapNameToOID("SHA256"));
                }
                }
                else {
                sig = csp.SignData(bytes, CryptoConfig.MapNameToOID("SHA256"));
                }
                return sig;
                }


                FYI the CryptoAPI is being deprecated in favor of Cryptography API: Next Generation. One way to do what you want with CNG in C# would be with System.Security.Cryptography.Cng:



                ...
                using (RSA rsa = new RSACng())
                {
                byte signature = rsa.SignData(message, hashAlgorithm, paddingMode);
                ...
                }






                share|improve this answer












                share|improve this answer



                share|improve this answer










                answered Dec 2 '18 at 3:28









                mnisticmnistic

                7,1711923




                7,1711923
































                    draft saved

                    draft discarded




















































                    Thanks for contributing an answer to Stack Overflow!


                    • Please be sure to answer the question. Provide details and share your research!

                    But avoid



                    • Asking for help, clarification, or responding to other answers.

                    • Making statements based on opinion; back them up with references or personal experience.


                    To learn more, see our tips on writing great answers.




                    draft saved


                    draft discarded














                    StackExchange.ready(
                    function () {
                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53449086%2fx509certificate2-with-private-key-signing-data-using-sha256withrsa%23new-answer', 'question_page');
                    }
                    );

                    Post as a guest















                    Required, but never shown





















































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown

































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown







                    Popular posts from this blog

                    Wiesbaden

                    Marschland

                    Dieringhausen