Decrypt my World

Cryptography, Security, Debugging and more!

How to call CryptEncodeObject in .NET (C#)

How to call CryptEncodeObject in .NET (C#)

  • Comments 4

Hi all,

The other day a colleague of mine was having some issues to call CryptEncodeObject from C#. In order to assist, I created this sample for him:

using System;

using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;

namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}

public const int X509_ASN_ENCODING = 0x00000001;
public const int PKCS_7_ASN_ENCODING = 0x00010000;
public const int X509_ENHANCED_KEY_USAGE = 36;

[StructLayout(LayoutKind.Sequential)]
private struct CERT_ENHKEY_USAGE
{
public int cUsageIdentifier;
public IntPtr rgpszUsageIdentifier;
}

[DllImport("crypt32.dll", CharSet = CharSet.Ansi, SetLastError = true)]
private static extern bool CryptEncodeObject(
int dwCertEncodingType,
int lpszStructType,
ref CERT_ENHKEY_USAGE pvStructInfo,
byte[] pbEncoded,
ref int pcbEncoded
);

private void button1_Click(object sender, EventArgs e)
{
// Variables
CERT_ENHKEY_USAGE usage = new CERT_ENHKEY_USAGE();
IntPtr OID = IntPtr.Zero;
int blobSize = 0;
byte[] blob = null;

try
{
// Prepare data to encode (CERT_ENHKEY_USAGE struct)
OID = Marshal.StringToHGlobalAnsi("1.3.6.1.4.1.311.101.11");
usage.rgpszUsageIdentifier = Marshal.AllocHGlobal(Marshal.SizeOf(OID));
Marshal.WriteIntPtr(usage.rgpszUsageIdentifier, OID);
usage.cUsageIdentifier = 1;

// Get size of encoded data
if (!CryptEncodeObject(
X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
X509_ENHANCED_KEY_USAGE,
ref usage,
null,
ref blobSize
))
{
int error = Marshal.GetLastWin32Error();
throw new Win32Exception(error);
}

// Get encoded data
blob = new byte[blobSize];
if (!CryptEncodeObject(
X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
X509_ENHANCED_KEY_USAGE,
ref usage,
blob,
ref blobSize
))
{
int error = Marshal.GetLastWin32Error();
throw new Win32Exception(error);
}

// Everything went well
MessageBox.Show("We got " + blob.Length.ToString() + " encoded bytes");
}
catch (Exception ex)
{
// Errors?
MessageBox.Show(ex.Message);
}
finally
{
// Clean up
if (!OID.Equals(IntPtr.Zero)) { Marshal.FreeHGlobal(OID); }
if (!usage.rgpszUsageIdentifier.Equals(IntPtr.Zero)) { Marshal.FreeHGlobal(usage.rgpszUsageIdentifier); }
}
}
}
}

I hope this helps.

Note I didn't have the opportunity to test it much, so if you have any issues with it, please let me know. Thx!

Regards,

 

Alex (Alejandro Campos Magencio)

  • hi,

    I testing you code e got it one problem,

    the date of sigin = 1899-12-30

    this is a default date of system, what modify to current date?

    tanks Mário

  • Sorry, but what date are you talking about? Are you talking about the CryptEncodeObject sample? I'm not using dates in there...

    Thx,

    Alex

  • Great article. Do you have any code snippet on X509_ALTERNATE_NAME extension using the CryptEncodeObject or CryptEncodeObjectEx API? thank you. shashank

  • Hi Shashank,

    I'm afraid what I got is what I posted. If you need assistance with this, please don't hesitate to open a support case with us so we can help you.

    Thank you.

    Alex

Page 1 of 1 (4 items)
Leave a Comment
  • Please add 6 and 2 and type the answer here:
  • Post
Translate This Page