See the MS sample RSACapiAndCngInterop.cpp, mainly the EncryptWithCngDecryptWithCapi function
How to implement NCryptEncrypt and NCryptDecrypt methods in C# using Microsoft Key Storage Provider?
Hi Team,
I want to implement NCryptEncrypt and NCryptDecrypt methods using Microsoft Key Storage Provider.
Please find the below link.
https://learn.microsoft.com/en-us/windows/win32/api/ncrypt/nf-ncrypt-ncryptencrypt
https://learn.microsoft.com/en-us/windows/win32/api/ncrypt/nf-ncrypt-ncryptdecrypt
I have tried following code but in NCryptEncrypt method I don't know what are the parameter values needs to be passed?
Please help me on this.
using static PInvoke.NCrypt;
public static void Encrypt(string plainText)
{
SafeProviderHandle ProviderHandle;
SafeKeyHandle KeyHandle;
string KeyName = "SampleStrongKey";
byte[] plainText_bytes = Encoding.ASCII.GetBytes(plainText);
SECURITY_STATUS secStatus = NCryptOpenStorageProvider(out ProviderHandle, "Microsoft Software Key Storage Provider", 0);
secStatus = NCryptCreatePersistedKey(ProviderHandle, out KeyHandle, "AES", KeyName, LegacyKeySpec.AT_SIGNATURE, NCryptCreatePersistedKeyFlags.NCRYPT_OVERWRITE_KEY_FLAG);
secStatus = NCryptEncrypt(?????????);
}
Regards,
Prabhakaran
2 answers
Sort by: Most helpful
-
-
Castorix31 81,831 Reputation points
2021-12-06T12:15:06.84+00:00 A quick conversion of MS code (Encrypt part) :
(test in a click of a Button)
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using System.Runtime.InteropServices; //https://github.com/Microsoft/Windows-classic-samples/blob/main/Samples/Security/RSACapiAndCngInterop/cpp/RSACapiAndCngInterop.cpp namespace CSharp_NCryptEncrypt { public partial class Form1 : Form { [DllImport("Ncrypt.dll", SetLastError = true, CharSet = CharSet.Unicode)] public static extern int NCryptOpenStorageProvider(out IntPtr phProvider, string pszProviderName, int dwFlags); [DllImport("Ncrypt.dll", SetLastError = true, CharSet = CharSet.Unicode)] public static extern int NCryptCreatePersistedKey(IntPtr hProvider, out IntPtr phKey, string pszAlgId, string pszKeyName, int dwLegacyKeySpec, int dwFlags); [DllImport("Ncrypt.dll", SetLastError = true, CharSet = CharSet.Unicode)] public static extern int NCryptSetProperty(IntPtr hObject, string pszProperty, [MarshalAs(UnmanagedType.LPArray)] byte[] pbInput, int cbInput, int dwFlags); [DllImport("Ncrypt.dll", SetLastError = true, CharSet = CharSet.Unicode)] public static extern int NCryptSetProperty(IntPtr hObject, string pszProperty, string pbInput, int cbInput, int dwFlags); [DllImport("Ncrypt.dll", SetLastError = true, CharSet = CharSet.Unicode)] public static extern int NCryptSetProperty(IntPtr hObject, string pszProperty, IntPtr pbInput, int cbInput, int dwFlags); [DllImport("Ncrypt.dll", SetLastError = true, CharSet = CharSet.Unicode)] public static extern int NCryptFinalizeKey(IntPtr hKey, int dwFlags); [DllImport("Ncrypt.dll", SetLastError = true, CharSet = CharSet.Unicode)] public static extern int NCryptEncrypt(IntPtr hKey, [In, MarshalAs(UnmanagedType.LPArray)] byte[] pbInput, int cbInput, [In] IntPtr pvPadding, [Out, MarshalAs(UnmanagedType.LPArray)] byte[] pbOutput, int cbOutput, [Out] out int pcbResult, int dwFlags); [DllImport("Ncrypt.dll", SetLastError = true, CharSet = CharSet.Unicode)] public static extern int NCryptExportKey(IntPtr hKey, IntPtr hExportKey, string pszBlobType, IntPtr pParameterList, [Out, MarshalAs(UnmanagedType.LPArray)] byte[] pbOutput, int cbOutput, [Out] out int pcbResult, int dwFlags); [DllImport("Ncrypt.dll", SetLastError = true, CharSet = CharSet.Unicode)] public static extern int NCryptDeleteKey(IntPtr hKey, int flags); [DllImport("Ncrypt.dll", SetLastError = true, CharSet = CharSet.Unicode)] public static extern int NCryptFreeObject(IntPtr hObject); [DllImport("Advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)] public static extern bool CryptDecrypt(IntPtr hKey, IntPtr hHash, bool Final, int dwFlags, [In, Out, MarshalAs(UnmanagedType.LPArray)] byte[] pbData, [In, Out] int pdwDataLen); [DllImport("Advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)] public static extern bool CryptImportKey(IntPtr hProv, [In, MarshalAs(UnmanagedType.LPArray)] byte[] pbData, int dwDataLen, IntPtr hPubKey, int dwFlags, [Out] out IntPtr phKey); [DllImport("Advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)] public static extern bool CryptDestroyKey(IntPtr hKey); [DllImport("Advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)] public static extern bool CryptAcquireContextW(out IntPtr phProv, string szContainer, string szProvider, int dwProvType, int dwFlags); [DllImport("Advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)] public static extern bool CryptReleaseContext(IntPtr hProv,int dwFlags); public const string MS_KEY_STORAGE_PROVIDER = "Microsoft Software Key Storage Provider"; public const string MS_SMART_CARD_KEY_STORAGE_PROVIDER= "Microsoft Smart Card Key Storage Provider"; public const string MS_PLATFORM_KEY_STORAGE_PROVIDER = "Microsoft Platform Crypto Provider"; public const string MS_NGC_KEY_STORAGE_PROVIDER = "Microsoft Passport Key Storage Provider"; public const string NCRYPT_RSA_ALGORITHM = "RSA"; public const string NCRYPT_AES_ALGORITHM = "AES"; public const int NCRYPT_OVERWRITE_KEY_FLAG = 0x00000080; public const int NCRYPT_ALLOW_EXPORT_FLAG = 0x00000001; public const int NCRYPT_ALLOW_PLAINTEXT_EXPORT_FLAG = 0x00000002; public const int NCRYPT_ALLOW_ARCHIVING_FLAG = 0x00000004; public const int NCRYPT_ALLOW_PLAINTEXT_ARCHIVING_FLAG = 0x00000008; public const string NCRYPT_UI_POLICY_PROPERTY = "UI Policy"; public const string NCRYPT_EXPORT_POLICY_PROPERTY = "Export Policy"; public const int NCRYPT_PERSIST_FLAG = unchecked((int)0x80000000); public const int NCRYPT_PERSIST_ONLY_FLAG = 0x40000000; public const int NCRYPT_NO_PADDING_FLAG = 0x00000001; // NCryptEncrypt/Decrypt public const int NCRYPT_PAD_PKCS1_FLAG = 0x00000002; // NCryptEncrypt/Decrypt NCryptSignHash/VerifySignature public const int NCRYPT_PAD_OAEP_FLAG = 0x00000004; // BCryptEncrypt/Decrypt public const int NCRYPT_PAD_PSS_FLAG = 0x00000008; // BCryptSignHash/VerifySignature public const int NCRYPT_PAD_CIPHER_FLAG = 0x00000010; // NCryptEncrypt/Decrypt public const int NCRYPT_ATTESTATION_FLAG = 0x00000020; // NCryptDecrypt for key attestation public const int NCRYPT_SEALING_FLAG = 0x00000100; // NCryptEncrypt/Decrypt for sealing public const string BCRYPT_RSAPUBLIC_BLOB = "RSAPUBLICBLOB"; public const string BCRYPT_RSAPRIVATE_BLOB = "RSAPRIVATEBLOB"; public const string LEGACY_RSAPUBLIC_BLOB = "CAPIPUBLICBLOB"; public const string LEGACY_RSAPRIVATE_BLOB = "CAPIPRIVATEBLOB"; public Form1() { InitializeComponent(); } private readonly byte[] Data = { 0x04, 0x87, 0xec, 0x66, 0xa8, 0xbf, 0x17, 0xa6, 0xe3, 0x62, 0x6f, 0x1a, 0x55, 0xe2, 0xaf, 0x5e, 0xbc, 0x54, 0xa4, 0xdc, 0x68, 0x19, 0x3e, 0x94 }; private void button1_Click(object sender, EventArgs e) { // EncryptWithCngDecryptWithCapi IntPtr CngProviderHandle = IntPtr.Zero; IntPtr CapiKeyHandle = IntPtr.Zero; int Policy = NCRYPT_ALLOW_PLAINTEXT_EXPORT_FLAG; int ResultLength = 0; int BlobLength = 0; int secStatus = NCryptOpenStorageProvider(out CngProviderHandle, MS_KEY_STORAGE_PROVIDER,0); if (secStatus == 0) { secStatus = NCryptCreatePersistedKey( CngProviderHandle, out CapiKeyHandle, NCRYPT_RSA_ALGORITHM, "test", 0, NCRYPT_OVERWRITE_KEY_FLAG); byte[] bytesPolicy = BitConverter.GetBytes(Policy); secStatus = NCryptSetProperty( CapiKeyHandle, NCRYPT_EXPORT_POLICY_PROPERTY, bytesPolicy, bytesPolicy.Length, NCRYPT_PERSIST_FLAG); secStatus = NCryptFinalizeKey(CapiKeyHandle, 0); int OutputLength = 0; secStatus = NCryptEncrypt( CapiKeyHandle, Data, Data.Length, IntPtr.Zero, null, 0, out OutputLength, NCRYPT_PAD_PKCS1_FLAG); byte[] Output = new byte[OutputLength]; //IntPtr hGlobal = Marshal.AllocHGlobal(OutputLength); //Output = (PBYTE)HeapAlloc(GetProcessHeap(), 0, OutputLength); secStatus = NCryptEncrypt( CapiKeyHandle, Data, Data.Length, IntPtr.Zero, Output, OutputLength, out ResultLength, NCRYPT_PAD_PKCS1_FLAG); secStatus = NCryptExportKey( CapiKeyHandle, IntPtr.Zero, LEGACY_RSAPRIVATE_BLOB, IntPtr.Zero, null, 0, out BlobLength, 0); byte[] Blob = new byte[BlobLength]; secStatus = NCryptExportKey( CapiKeyHandle, IntPtr.Zero, LEGACY_RSAPRIVATE_BLOB, IntPtr.Zero, Blob, BlobLength, out BlobLength, 0); // Decrypt to be added... // ReverseBytes(Output, OutputLength); //if (CngTmpKeyHandle != IntPtr.Zero) //{ // CryptDestroyKey(CngTmpKeyHandle); //} //if (CapiLocProvHandle != IntPtr.Zero) //{ // CryptReleaseContext(CapiLocProvHandle, 0); //} if (CapiKeyHandle != IntPtr.Zero) { NCryptDeleteKey(CapiKeyHandle, 0); } if (CngProviderHandle != IntPtr.Zero) { NCryptFreeObject(CngProviderHandle); } } } } }