Retired Microsoft Blog disclaimer

This directory is a mirror of retired "Decrypt My World" MSDN blog and is provided as is. All posting authorship and copyrights belong to respective authors.

Posts on this page:

Original URL: https://blogs.msdn.microsoft.com/alejacma/2011/02/18/how-to-disable-this-web-site-is-attempting-to-perform-a-digital-certificate-operation-on-your-behalf-message/
Post name: How to disable "This Web site is attempting to perform a digital certificate operation on your behalf" message
Original author: Alejandro Campos Magencio
Posting date: 2011-02-18T06:08:00+00:00


Hi all,

A customer of mine was using some web pages to enroll certificates. When using them on Windows 7 and IE8/IE9, they got a popup dialog with a message like the following:

---------------------------
Web Access Confirmation
---------------------------
This Web site is attempting to perform a digital certificate operation on your behalf:

https://myserver/certsrv/certrqma.asp

You should only allow known Web sites to perform digital certificate operations on your behalf.

Do you want to allow this operation?
---------------------------
Yes No
---------------------------

They were wondering if there was a way to get rid of this security warning, in order to get a seamless certificate enrollment experience. They managed to do this on Vista SP2with IE7/IE8 by adding the site to the trusted sites zone and, for that zone, enabling “Initialize and script ActiveX controls not marked as safe for scripting”. If they changed it back to Disabled, the popup returned. But that didn't work on Windows 7.

And the answer is NO, we cannot disable this security warning on Windows 7. The enrollment is done by CertEnroll control. This control will always show the security warning when running within a browser. This is by design.

Actually, if CertEnroll cannot show that warning for some reason, it will just stop working. That is what happened in this bug I worked on some time ago:

The CertEnroll control does not work in Internet Explorer 8 on a computer that is running Windows 7 or Windows Server 2008 R2

The only way to get rid of this warning is to use CertEnroll out of the browser, in e.g. a WinForms app. I've seen some people in the past using ClickOnce apps to enroll certs without user interaction. And those apps were accessed via web. But CertEnroll itself was not running inthe browser itself.

And why do those settings work on Vista SP2? I debugged CertEnroll in both Vista SP2and Win7, and saw that the code is different. Vista shows the warning in a different place/function. That function is affected by the configuration of Internet Explorer. When we enable “Initialize and script ActiveX controls not marked as safe for scripting”, that function thinks we are not in a web environment, and it won’t show the dialog.

But wait, that is what happens on Vista SP2 RTM. I checked the latest source code for Vista, the one that includes the hotfixes we released recently, and I could see that we have updated CertEnroll code! Now on newer versions of CertEnroll for Vista, we will always show the security warning too regardless of IE configuration!

Certenroll version for Vista SP2 RTM is 6.0.6002.18005. So I installed in my environment this newer version I found:

983557 Error message when you try to request a certificate in Windows Vista or in Windows Server 2008: "The filename or extension is too long. (0x800700CE)"
"
Certenroll.dll 6.0.6002.22401
"

And with that new version it doesn't matter if I enable or not “Initialize and script ActiveX controls not marked as safe for scripting”. I will always see the security warning!

So summing up, we cannot get rid of the security warning on Windows 7, and we have updated Windows Vista to behave in the same way.

I hope this helps.

Regards,

 

Alex (Alejandro Campos Magencio)

 

Original URL: https://blogs.msdn.microsoft.com/alejacma/2011/02/18/how-to-disable-the-pop-up-that-windows-shows-when-an-app-crashes/
Post name: How to disable the pop up that Windows shows when an app crashes
Original author: Alejandro Campos Magencio
Posting date: 2011-02-18T04:52:56+00:00


Hi all,

The other day a customer of mine was trying to disable the pop up dialog that Windows shows after an application crashes.

On Windows XP, they could get rid of it by going to "Control Panel > System Properties > Advanced > Error reporting", clicking on "Disable error reporting" and disabling "But notify me when critical error occurs".

On Windows 7 on the other hand, if we go to "Control Panel\System and Security\Action Center\Problem Reporting Settings" and select "Never check for solutions",we still see a dialog when app crashes. The dialog says:

[Window Title]
MyAppName

[Main Instruction]
MyAppName has stopped working

[Content]
A problem caused the program to stop working correctly. Please close the program.

[Close the program] [Debug the program]

A command like this won't work, as it has the same effect than the control panel: serverWerOptin /disable.

We will have to set this registry value to 1 instead: HKEY_CURRENT_USER\Software\ Microsoft\Windows\Windows Error Reporting\DontShowUI

I hope this helps.

Regards,

Alex (Alejandro Campos Magencio)

Original URL: https://blogs.msdn.microsoft.com/alejacma/2011/02/18/how-to-verify-signatures-using-a-temporary-keyset-in-net/
Post name: How to verify signatures using a temporary keyset in .NET
Original author: Alejandro Campos Magencio
Posting date: 2011-02-18T04:25:23+00:00


Hi all,

Some time ago a customer of mine had issues to verify signatures with RSACryptoServiceProvider when users had a mandatory and/or roaming profile, as he was getting the following exception:

"System.Security.Cryptography.CryptographicException: Cryptographic Service Provider (CSP) for this implementation could not be acquired".

I already talked about this: RSACryptoServiceProvider fails when used with mandatory profiles. There I mentioned the following workaround:

The way to i.e. verify signatures using temporary keysets in .NET would be to use CryptoAPI directly through P/Invoke (Platform Invoke), instead of using RSACryptoServiceProvider.

So I created the following sample that uses CryptoAPI via P/Invoke to be able to verify signatures using a temporary keyset. Note that the sample creates the signature with RSACryptoServiceProvider, and verifies it with CryptVerifySignature API after selectingthe temporary keyset.

Form1.cs:

using System;
using System.Xml;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.Security.Cryptography;
using System.Runtime.InteropServices;
using System.IO;

namespace WindowsApplication1
{
 /// <summary>
 /// Summary description for Form1.
 /// </summary>
 public class Form1 : System.Windows.Forms.Form
 {
  private System.Windows.Forms.GroupBox groupBox1;
  private System.Windows.Forms.GroupBox groupBox2;
  private System.Windows.Forms.Button button11;
  private System.Windows.Forms.Button button21;
  private System.Windows.Forms.TextBox textBox11;
  private System.Windows.Forms.Label label11;
  private System.Windows.Forms.TextBox textBox21;
  private System.Windows.Forms.Label label31;
  private System.Windows.Forms.TextBox textBox31;
  private System.Windows.Forms.Label label21;
  private System.Windows.Forms.Button button22;
  private System.Windows.Forms.TextBox textBox12;
  private System.Windows.Forms.Label label12;
  private System.Windows.Forms.TextBox textBox22;
  private System.Windows.Forms.Label label32;
  private System.Windows.Forms.TextBox textBox32;
  private System.Windows.Forms.Label label22;
  private System.Windows.Forms.Button button12;
  /// <summary>
  /// Required designer variable.
  /// </summary>
  private System.ComponentModel.Container components = null;

  public Form1()
  {
   //
   // Required for Windows Form Designer support
   //
   InitializeComponent();

   //
   // TODO: Add any constructor code after InitializeComponent call
   //
  }

  /// <summary>
  /// Clean up any resources being used.
  /// </summary>
  protected override void Dispose( bool disposing )
  {
   if( disposing )
   {
    if (components != null) 
    {
     components.Dispose();
    }
   }
   base.Dispose( disposing );
  }

  #region Windows Form Designer generated code
  /// <summary>
  /// Required method for Designer support - do not modify
  /// the contents of this method with the code editor.
  /// </summary>
  private void InitializeComponent()
  {
   this.button11 = new System.Windows.Forms.Button();
   this.button21 = new System.Windows.Forms.Button();
   this.textBox11 = new System.Windows.Forms.TextBox();
   this.label11 = new System.Windows.Forms.Label();
   this.textBox21 = new System.Windows.Forms.TextBox();
   this.label31 = new System.Windows.Forms.Label();
   this.textBox31 = new System.Windows.Forms.TextBox();
   this.label21 = new System.Windows.Forms.Label();
   this.groupBox1 = new System.Windows.Forms.GroupBox();
   this.groupBox2 = new System.Windows.Forms.GroupBox();
   this.button22 = new System.Windows.Forms.Button();
   this.textBox12 = new System.Windows.Forms.TextBox();
   this.label12 = new System.Windows.Forms.Label();
   this.textBox22 = new System.Windows.Forms.TextBox();
   this.label32 = new System.Windows.Forms.Label();
   this.textBox32 = new System.Windows.Forms.TextBox();
   this.label22 = new System.Windows.Forms.Label();
   this.button12 = new System.Windows.Forms.Button();
   this.groupBox1.SuspendLayout();
   this.groupBox2.SuspendLayout();
   this.SuspendLayout();
   // 
   // button11
   // 
   this.button11.Location = new System.Drawing.Point(8, 64);
   this.button11.Name = "button11";
   this.button11.Size = new System.Drawing.Size(216, 32);
   this.button11.TabIndex = 0;
   this.button11.Text = "Sign";
   this.button11.Click += new System.EventHandler(this.button11_Click);
   // 
   // button21
   // 
   this.button21.Location = new System.Drawing.Point(8, 360);
   this.button21.Name = "button21";
   this.button21.Size = new System.Drawing.Size(216, 32);
   this.button21.TabIndex = 1;
   this.button21.Text = "Verify";
   this.button21.Click += new System.EventHandler(this.button21_Click);
   // 
   // textBox11
   // 
   this.textBox11.Location = new System.Drawing.Point(8, 40);
   this.textBox11.Name = "textBox11";
   this.textBox11.Size = new System.Drawing.Size(216, 20);
   this.textBox11.TabIndex = 2;
   this.textBox11.Text = "OwT4Zk1hjsnSDOBdGSlkxdWGgoc=";
   // 
   // label11
   // 
   this.label11.Location = new System.Drawing.Point(8, 24);
   this.label11.Name = "label11";
   this.label11.Size = new System.Drawing.Size(104, 16);
   this.label11.TabIndex = 3;
   this.label11.Text = "Hash (Base64)";
   // 
   // textBox21
   // 
   this.textBox21.Location = new System.Drawing.Point(8, 120);
   this.textBox21.Multiline = true;
   this.textBox21.Name = "textBox21";
   this.textBox21.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
   this.textBox21.Size = new System.Drawing.Size(216, 104);
   this.textBox21.TabIndex = 4;
   this.textBox21.Text = "";
   // 
   // label31
   // 
   this.label31.Location = new System.Drawing.Point(8, 232);
   this.label31.Name = "label31";
   this.label31.Size = new System.Drawing.Size(168, 16);
   this.label31.TabIndex = 5;
   this.label31.Text = "Signature (Base64)";
   // 
   // textBox31
   // 
   this.textBox31.Location = new System.Drawing.Point(8, 248);
   this.textBox31.Multiline = true;
   this.textBox31.Name = "textBox31";
   this.textBox31.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
   this.textBox31.Size = new System.Drawing.Size(216, 104);
   this.textBox31.TabIndex = 6;
   this.textBox31.Text = "";
   // 
   // label21
   // 
   this.label21.Location = new System.Drawing.Point(8, 104);
   this.label21.Name = "label21";
   this.label21.Size = new System.Drawing.Size(104, 16);
   this.label21.TabIndex = 7;
   this.label21.Text = "RSA object (XML)";
   // 
   // groupBox1
   // 
   this.groupBox1.Controls.Add(this.button21);
   this.groupBox1.Controls.Add(this.textBox11);
   this.groupBox1.Controls.Add(this.label11);
   this.groupBox1.Controls.Add(this.textBox21);
   this.groupBox1.Controls.Add(this.label31);
   this.groupBox1.Controls.Add(this.textBox31);
   this.groupBox1.Controls.Add(this.label21);
   this.groupBox1.Controls.Add(this.button11);
   this.groupBox1.Location = new System.Drawing.Point(8, 8);
   this.groupBox1.Name = "groupBox1";
   this.groupBox1.Size = new System.Drawing.Size(232, 400);
   this.groupBox1.TabIndex = 8;
   this.groupBox1.TabStop = false;
   this.groupBox1.Text = "No P/Invoke";
   // 
   // groupBox2
   // 
   this.groupBox2.Controls.Add(this.button22);
   this.groupBox2.Controls.Add(this.textBox12);
   this.groupBox2.Controls.Add(this.label12);
   this.groupBox2.Controls.Add(this.textBox22);
   this.groupBox2.Controls.Add(this.label32);
   this.groupBox2.Controls.Add(this.textBox32);
   this.groupBox2.Controls.Add(this.label22);
   this.groupBox2.Controls.Add(this.button12);
   this.groupBox2.Location = new System.Drawing.Point(248, 8);
   this.groupBox2.Name = "groupBox2";
   this.groupBox2.Size = new System.Drawing.Size(232, 400);
   this.groupBox2.TabIndex = 9;
   this.groupBox2.TabStop = false;
   this.groupBox2.Text = "P/Invoke";
   // 
   // button22
   // 
   this.button22.Location = new System.Drawing.Point(8, 360);
   this.button22.Name = "button22";
   this.button22.Size = new System.Drawing.Size(216, 32);
   this.button22.TabIndex = 1;
   this.button22.Text = "Verify";
   this.button22.Click += new System.EventHandler(this.button22_Click);
   // 
   // textBox12
   // 
   this.textBox12.Location = new System.Drawing.Point(8, 40);
   this.textBox12.Name = "textBox12";
   this.textBox12.Size = new System.Drawing.Size(216, 20);
   this.textBox12.TabIndex = 2;
   this.textBox12.Text = "OwT4Zk1hjsnSDOBdGSlkxdWGgoc=";
   // 
   // label12
   // 
   this.label12.Location = new System.Drawing.Point(8, 24);
   this.label12.Name = "label12";
   this.label12.Size = new System.Drawing.Size(104, 16);
   this.label12.TabIndex = 3;
   this.label12.Text = "Hash (Base64)";
   // 
   // textBox22
   // 
   this.textBox22.Location = new System.Drawing.Point(8, 120);
   this.textBox22.Multiline = true;
   this.textBox22.Name = "textBox22";
   this.textBox22.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
   this.textBox22.Size = new System.Drawing.Size(216, 104);
   this.textBox22.TabIndex = 4;
   this.textBox22.Text = "";
   // 
   // label32
   // 
   this.label32.Location = new System.Drawing.Point(8, 232);
   this.label32.Name = "label32";
   this.label32.Size = new System.Drawing.Size(168, 16);
   this.label32.TabIndex = 5;
   this.label32.Text = "Signature (Base64)";
   // 
   // textBox32
   // 
   this.textBox32.Location = new System.Drawing.Point(8, 248);
   this.textBox32.Multiline = true;
   this.textBox32.Name = "textBox32";
   this.textBox32.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
   this.textBox32.Size = new System.Drawing.Size(216, 104);
   this.textBox32.TabIndex = 6;
   this.textBox32.Text = "";
   // 
   // label22
   // 
   this.label22.Location = new System.Drawing.Point(8, 104);
   this.label22.Name = "label22";
   this.label22.Size = new System.Drawing.Size(104, 16);
   this.label22.TabIndex = 7;
   this.label22.Text = "RSA object (XML)";
   // 
   // button12
   // 
   this.button12.Location = new System.Drawing.Point(8, 64);
   this.button12.Name = "button12";
   this.button12.Size = new System.Drawing.Size(216, 32);
   this.button12.TabIndex = 0;
   this.button12.Text = "Sign";
   this.button12.Click += new System.EventHandler(this.button12_Click);
   // 
   // Form1
   // 
   this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
   this.ClientSize = new System.Drawing.Size(488, 414);
   this.Controls.Add(this.groupBox1);
   this.Controls.Add(this.groupBox2);
   this.Name = "Form1";
   this.Text = "Form1";
   this.groupBox1.ResumeLayout(false);
   this.groupBox2.ResumeLayout(false);
   this.ResumeLayout(false);

  }
  #endregion

  /// <summary>
  /// The main entry point for the application.
  /// </summary>
  [STAThread]
  static void Main() 
  {
   Application.Run(new Form1());
  }

  private void button11_Click(object sender, System.EventArgs e)
  {
   textBox21.Text = "";
   textBox31.Text = "";

   // Create RSA object and show it
   RSACryptoServiceProvider RSA = new RSACryptoServiceProvider();
   textBox21.Text = RSA.ToXmlString(false);

   // Sign hash
   RSAPKCS1SignatureFormatter RSAFormatter = new RSAPKCS1SignatureFormatter(RSA);
   RSAFormatter.SetHashAlgorithm("SHA1");
   byte[] signedHashValue = RSAFormatter.CreateSignature(
    Convert.FromBase64String(textBox11.Text)); 
  
   // Show signature
   textBox31.Text = Convert.ToBase64String(signedHashValue);  
  }

  private void button21_Click(object sender, System.EventArgs e)
  {
   // Re-create RSA object
   RSACryptoServiceProvider RSA = new RSACryptoServiceProvider();
   RSA.FromXmlString(textBox21.Text);

   // Verify signature 
   RSAPKCS1SignatureDeformatter RSADeformatter = new RSAPKCS1SignatureDeformatter(RSA);
   RSADeformatter.SetHashAlgorithm("SHA1");
   if (RSADeformatter.VerifySignature(
    Convert.FromBase64String(textBox11.Text), 
    Convert.FromBase64String(textBox31.Text))
    )
   { 
    MessageBox.Show("Signature verified!");
   } 
   else 
   {
    MessageBox.Show("Signature NOT verified!");
   }
  }


  private void button12_Click(object sender, System.EventArgs e)
  {
   textBox22.Text = "";
   textBox32.Text = "";

   // Create RSA object and show it
   RSACryptoServiceProvider RSA = new RSACryptoServiceProvider();
   textBox22.Text = RSA.ToXmlString(false);

   // Sign hash
   RSAPKCS1SignatureFormatter RSAFormatter = new RSAPKCS1SignatureFormatter(RSA);
   RSAFormatter.SetHashAlgorithm("SHA1");
   byte[] signedHashValue = RSAFormatter.CreateSignature(
    Convert.FromBase64String(textBox12.Text)); 
  
   // Show signature
   textBox32.Text = Convert.ToBase64String(signedHashValue);   
  }

  private void button22_Click(object sender, System.EventArgs e)
  {
   // Variables
   IntPtr hProv = IntPtr.Zero;
   String pszContainer = null;
   String pszProvider = null;
   UInt32 dwProvType = 0;
   UInt32 dwFlags = 0;
   IntPtr hHash = IntPtr.Zero;
   Byte[] pbHash = null;
   IntPtr hPubKey = IntPtr.Zero;
   Byte[] pbSignature = null;
   Byte[] pbModulus = null;
   Byte[] pbExponent = null;
   Byte[] pbPubKey = null;

   try 
   {
    // Acquire CSP
    hProv = IntPtr.Zero;  
    pszContainer = null; // Required for crypt_verifycontext 
    pszProvider = null; // Can use null for default provider
    dwProvType  = Win32.PROV_RSA_FULL;
    dwFlags = Win32.CRYPT_VERIFYCONTEXT; //No private key access required.

    if (!Win32.CryptAcquireContext(ref hProv, pszContainer, pszProvider, dwProvType, dwFlags))
    {
     throw new Exception("CryptAcquireContext error", new Win32Exception(Marshal.GetLastWin32Error()));
    }

    // Create hash object
    hHash = IntPtr.Zero;

    if (!Win32.CryptCreateHash(hProv, Win32.CALG_SHA1, IntPtr.Zero, 0, ref hHash))
    {
     throw new Exception("CryptCreateHash error", new Win32Exception(Marshal.GetLastWin32Error()));
    }

    // Fill hash object with our hash
    pbHash = Convert.FromBase64String(textBox12.Text);

    if (!Win32.CryptSetHashParam(hHash, Win32.HP_HASHVAL, pbHash, 0))
    {
     throw new Exception("CryptSetHashParam error", new Win32Exception(Marshal.GetLastWin32Error()));
    }

    // Import public key
    //
    // Public Key BLOB:
    // "
    //  PUBLICKEYSTRUC blobheader;
    //  RSAPUBKEY rsapubkey;
    //  BYTE modulus[rsapubkey.bitlen/8];
    // "
    XmlDocument xml = new XmlDocument();
    xml.InnerXml = textBox22.Text;
    pbModulus = Convert.FromBase64String(xml.FirstChild.ChildNodes.Item(0).InnerText);
    pbExponent = Convert.FromBase64String(xml.FirstChild.ChildNodes.Item(1).InnerText);

    MemoryStream keyBlob = new MemoryStream(
     Marshal.SizeOf(typeof(Win32.PUBLICKEYSTRUC)) +
     Marshal.SizeOf(typeof(Win32.RSAPUBKEY)) +
     pbModulus.Length
    );
    BinaryWriter bw = new BinaryWriter(keyBlob);

    bw.Write((Byte)Win32.PUBLICKEYBLOB);  // blobheader.bType
    bw.Write((Byte)Win32.CUR_BLOB_VERSION);  // blobheader.bVersion
    bw.Write((UInt16)0);      // blobheader.reserved
    bw.Write((UInt32)Win32.CALG_RSA_SIGN);  // blobheader.aiKeyAlg

    bw.Write((UInt32)0x31415352);    // rsapubkey.magic = "RSA1"
    bw.Write((UInt32)(pbModulus.Length * 8)); // rsapubkey.bitlen
    
    // rsapubkey.pubexp 
    Byte[] buffer = new Byte[Marshal.SizeOf(typeof(UInt32))];
    Array.Copy(pbExponent, 0, buffer, 0, pbExponent.Length);
    bw.Write(buffer);

    // modulus
    Array.Reverse(pbModulus); 
    bw.Write(pbModulus);      

    pbPubKey = keyBlob.ToArray();

    if (!Win32.CryptImportKey(hProv, pbPubKey, pbPubKey.Length, IntPtr.Zero, 0, ref hPubKey))
    {
     throw new Exception("CryptImportKey error", new Win32Exception(Marshal.GetLastWin32Error()));
    }

    // Verify signature
    pbSignature = Convert.FromBase64String(textBox32.Text);
    Array.Reverse(pbSignature);

    if (!Win32.CryptVerifySignature(hHash, pbSignature, pbSignature.Length, hPubKey, null, 0))
    {
     throw new Exception("CryptVerifySignature error", new Win32Exception(Marshal.GetLastWin32Error()));
    } 
    else 
    {
     MessageBox.Show("Signature verified!!!");
    }
   } 
   catch (Exception ex)
   {
    // Any errors?
    string msg;
    if (ex.InnerException == null) 
    {
     msg = ex.Message;
    } 
    else 
    {
     msg = ex.Message + " --> " + ex.InnerException.Message;
    }
    MessageBox.Show(msg);
   }
   finally 
   {
    // Destroy hash
    if (hHash != IntPtr.Zero) 
    {
     Win32.CryptDestroyHash(hHash);
    }

    // Destroy public key
    if (hPubKey != IntPtr.Zero) 
    {
     Win32.CryptDestroyKey(hPubKey);
    }

    // Release the CSP
    //
    if (hProv != IntPtr.Zero) 
    {
     Win32.CryptReleaseContext(hProv, 0);
    }  
   }
  }
 }
}

Win32.cs:

using System;
using System.Windows.Forms;
using System.Runtime.InteropServices;
public class Win32
{

 #region CONSTS

 public const UInt32 CALG_SHA1 = (4 << 13) | 4;
 public const UInt32 CALG_RSA_SIGN = (1 << 13) | (2 << 9);
 public const UInt32 PROV_RSA_FULL = 0x00000001;
 public const UInt32 CRYPT_VERIFYCONTEXT = 0xF0000000; //No private key access required
 public const UInt32 X509_ASN_ENCODING = 0x00000001;
 public const UInt32 PKCS_7_ASN_ENCODING = 0x00010000;
 public const UInt32 HP_HASHVAL = 0x00000002;
 public const UInt32 HP_HASHSIZE = 0x00000004;
 public const UInt32 PUBLICKEYBLOBEX = 0x0A;
 public const UInt32 PUBLICKEYBLOB = 0x06;
 public const UInt32 CUR_BLOB_VERSION = 0x02;
 public const UInt32 CRYPT_EXPORTABLE = 0x00000001;

 #endregion

 #region STRUCTS

 [StructLayout(LayoutKind.Sequential)]
 public struct PUBLICKEYSTRUC
 {
  public Byte bType;
  public Byte bVersion;
  public UInt16 reserved;
  public UInt32 aiKeyAlg;
 }

 [StructLayout(LayoutKind.Sequential)]
 public struct RSAPUBKEY 
 {
  public UInt32 magic;
  public UInt32 bitlen;
  public UInt32 pubexp;
 }

 #endregion

 #region FUNCTIONS

 [DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)]
 public static extern bool CryptAcquireContext(
  ref IntPtr hProv,
  String pszContainer,
  String pszProvider,
  UInt32 dwProvType,
  UInt32 dwFlags
 );

 [DllImport("advapi32.dll", SetLastError=true)]
 public static extern bool CryptCreateHash(
  IntPtr hProv,
  UInt32 Algid,
  IntPtr hKey,
  UInt32 dwFlags,
  ref IntPtr phHash
 );

 [DllImport("advapi32.dll", SetLastError=true)]
 public static extern bool CryptGetHashParam(
  IntPtr hHash,
  UInt32 dwParam,
  ref UInt32 pbData,
  ref UInt32 pdwDataLen,
  UInt32 dwFlags
 );

 [DllImport("advapi32.dll", SetLastError=true)]
 public static extern bool CryptSetHashParam(
  IntPtr hHash,
  UInt32 dwParam,
  Byte[] pbData,
  UInt32 dwFlags
 );

 [DllImport("crypt32.dll", CharSet=CharSet.Auto, SetLastError=true)]
 public static extern bool CryptImportPublicKeyInfo(
  IntPtr hCryptProv,
  UInt32 dwCertEncodingType,
  IntPtr pInfo,
  ref IntPtr phKey
 );

 [DllImport("advapi32.dll", SetLastError=true)]
 public static extern bool CryptImportKey(
  IntPtr hProv,
  Byte[] pbData,
  Int32 dwDataLen,
  IntPtr hPubKey,
  UInt32 dwFlags,
  ref IntPtr phKey
 );

 [DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)]
 public static extern bool CryptVerifySignature(
  IntPtr hHash,
  Byte[] pbSignature,
  Int32 dwSigLen,
  IntPtr hPubKey,
  String sDescription,
  UInt32 dwFlags
 );

 [DllImport("advapi32.dll", SetLastError=true)]
 public static extern bool CryptDestroyKey(
  IntPtr hKey
 );

 [DllImport("advapi32.dll", SetLastError=true)]
 public static extern bool CryptDestroyHash(
  IntPtr hHash
 );

 [DllImport("advapi32.dll", SetLastError=true)]
 public static extern bool CryptReleaseContext(
  IntPtr hProv,
  UInt32 dwFlags
 );

 [DllImport("advapi32.dll", SetLastError=true)]
 public static extern bool CryptGenKey(
  IntPtr hProv,
  UInt32 Algid,
  UInt32 dwFlags,
  ref IntPtr phKey
 );

 [DllImport("advapi32.dll", SetLastError=true)]
 public static extern bool CryptExportKey(
  IntPtr hKey,
  IntPtr hExpKey,
  UInt32 dwBlobType,
  UInt32 dwFlags,
  Byte[] pbData,
  ref UInt32 pdwDataLen
 );

 // Helper function to convert struts & classes to byte array
 public static byte[] RawSerialize(object anything) 
 { 
  int rawsize = Marshal.SizeOf(anything); 
  IntPtr buffer = Marshal.AllocHGlobal(rawsize); 
  Marshal.StructureToPtr(anything, buffer, false); 
  byte[] rawdatas = new byte[rawsize]; 
  Marshal.Copy(buffer, rawdatas, 0, rawsize); 
  Marshal.FreeHGlobal(buffer); 
  return rawdatas; 
 } 

 #endregion 
}

I hope this helps.

Regards,

 

Alex (Alejandro Campos Magencio)

Original URL: https://blogs.msdn.microsoft.com/alejacma/2011/02/18/unable-to-import-a-key-into-keynumber-signature-with-rsacryptoserviceprovider/
Post name: Unable to import a key into KeyNumber.Signature with RSACryptoServiceProvider
Original author: Alejandro Campos Magencio
Posting date: 2011-02-18T03:26:00+00:00


Hi all,

The other day a customer of mine was having an issue when importing key pairs with .NET's RSACryptoServiceProvider. When setting KeyNumber parameter to KeyNumber.Exchange everything seems to be fine. But when setting the KeyNumber parameter to KeyNumber.Signature the key pair is imported to the KeyNumber.Exchange slot just as if you haven’t set the KeyNumber parameter.

I could reproduce the issue with the following sample:

private void button1_Click(object sender, EventArgs e)
{
    // WORKS
    string keypair1 = GetKey(KeyNumber.Exchange);
    StoreKeyInContainer(KeyNumber.Exchange, keypair1);
    CheckKey(KeyNumber.Exchange, keypair1);

    // FAILS BUT IT SHOULD WORK
    string keypair2 = GetKey(KeyNumber.Signature);
    StoreKeyInContainer(KeyNumber.Signature, keypair2);
    CheckKey(KeyNumber.Signature, keypair2);

    // WORKS BUT IT SHOULD FAIL
    string keypair3 = GetKey(KeyNumber.Signature);
    StoreKeyInContainer(KeyNumber.Signature, keypair3);
    CheckKey(KeyNumber.Exchange, keypair3);
}

public static string GetKey(KeyNumber theKeyNumber)
{
    CspParameters parms;
    RSACryptoServiceProvider rsa;

    parms = new CspParameters(1);
    parms.Flags = CspProviderFlags.UseMachineKeyStore;
    parms.KeyNumber = (Int32)theKeyNumber;
    parms.KeyContainerName = "Origin";
    rsa = new RSACryptoServiceProvider(parms);
    return rsa.ToXmlString(true);
}

public static void StoreKeyInContainer(KeyNumber theKeyNumber, String theXmlKeyPair)
{
    CspParameters  parms;
    RSACryptoServiceProvider rsa;

    parms = new CspParameters(1);
    parms.Flags = CspProviderFlags.UseMachineKeyStore;
    parms.KeyContainerName = "Test";
    parms.KeyNumber = (Int32) theKeyNumber;
    rsa = new RSACryptoServiceProvider(parms);
    rsa.FromXmlString(theXmlKeyPair);
}

public static void CheckKey(KeyNumber theKeyNumber, String theXmlKeyPair)
{
    CspParameters  parms;
    RSACryptoServiceProvider rsa;

    parms = new CspParameters(1);
    parms.Flags = CspProviderFlags.UseMachineKeyStore;
    parms.KeyContainerName = "Test";
    parms.KeyNumber = (Int32) theKeyNumber;
    rsa = new RSACryptoServiceProvider(parms);
    if (theXmlKeyPair.Equals(rsa.ToXmlString(true)))
    {
        MessageBox.Show("Success!");
    }
    else
    {
        MessageBox.Show("Failure!");
    }
}

We checked RSACryptoServiceProvicer's source code (e.g. with Reflector) and saw that RSACryptoServiceProvicer.ImportParameters always calls Utils._ImportKey with CALG_RSA_KEYX. We never use CALG_RSA_SIGN.

This issue happens (at least) on .NET Framework 2.0/3.5/4.0.

I talked to our Product Group about this, and they confirmed that this is issue is by design. They intentionally ignore KeyNumber param.

The good news is that there is a workaround. As we've seen, RSACryptoServiceProvider is hard-coded to use CALG_RSA_KEYX for importing RSA parameters. What we can do, however, is import a raw CAPI key blob into either key number.Unfortunatelly, there is no managed API that builds that up for us, sowe are going to have to do that ourselves. The format is documented here: Private Key BLOBs. By setting the aiKeyAlgID field of the BLOBHEADER to eitherCALG_RSA_KEYX or CALG_RSA_SIGN you can pick which portion of the key container your blob will go into.

I did something similar in the past to import a key blob in .NET. I have attached a sample that uses CryptoAPI via P/Invoke to be able to verify signatures using a temporary keyset: How to verify signatures using a temporary keyset in .NET. Check method button22_Click for the verification code. There I create a key blob from an XML and import it via CryptoAPI.

I hope this helps.

Regards,

Alex (Alejandro Campos Magencio)

Original URL: https://blogs.msdn.microsoft.com/alejacma/2011/02/18/big-delay-when-calling-x509certificate2-constructor/
Post name: Big delay when calling X509Certificate2 constructor
Original author: Alejandro Campos Magencio
Posting date: 2011-02-18T03:23:00+00:00


Hi all,

The other day a customer of mine was experiencing big delays when making this kind of calls to X509Certificate2 constructor:

X509Certificate2 cert = new X509Certificate2(byteArray);

Sometimes this process was almost instant, sometimes it took up to 2 minutes to create the object!!! During the reproduction of the issue, CPU usage was very high.

I debugged the issue and found out that it is related to this:

X509Certificate creates temporary files which are never deleted

When calling this specific X509Certificate2 constructor, .NET ends up calling CryptQueryObject API behind the scenes. This API will make calls to GetTempFileName API, andthe delay is happening inthere.

This is a known issue on a couple Window versions, and fortunately there is a fix for it:

On a Windows Server 2003-based or Windows Server 2008-based client computer, the system does not delete a temporary file that is created when an application calls the "CryptQueryObject" function

My customer had a few hundred temp files more than 65,000. Having so many files seriously affects the performance of GetTempFileName, which explains the high CPU usage.

After deleting the files, performance was as expected.Still, we need to install the fixso those files are deleted when they should.

Regards,

 

Alex (Alejandro Campos Magencio)