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/2008/06/30/threading-issues-with-cryptoapi/
Post name: Threading issues with CryptoAPI
Original author: Alejandro Campos Magencio
Posting date: 2008-06-30T08:55:00+00:00


Hi all,

Let's talk a bit about concurrency in CryptoAPI. When calling CryptoAPI from different threads, we have to take into consideration that key handles are not thread safe.

The following document describes the threading issues when dealing with key handles in applications: Threading Issues with Cryptographic Service Providers.

Imagine that you have developed an application which creates a session key on startup. The handles to the CSP and session key are stored globally.

According to previous article, the status of the key may be important:

Most algorithms and modes require that data be decrypted in the same order that it was encrypted. This is a difficult task in a multithreaded environment because use of a critical section will not address the ordering issue. If you are using a block cipher (that is, RC2, DES, or 3DES) in ECB cipher mode, then this issue is not a factor because the internal key state does not change. However, ECB is not the default cipher mode. CBC is the default cipher mode. With CBC cipher mode, the internal key state does change.

For instance, when CryptEncrypt/CryptDecrypt is used with the value TRUE for the Final flag, the HCRYPTKEY is actually finalized and shouldn’t be used again.
So when you encrypt/decrypt data you can use a duplicated local HCRYPTKEY handle to perform the operation. You can duplicate the global HCRYPTKEY handle by calling CryptDuplicateKeyAPI.Global HCRYPTKEY will remain in its initial state. Make sure that you call CryptDestroyKey on the local handle. This is Microsoft’s recommended approach.

I hope this helps.

Regards,

Alex (Alejandro Campos Magencio)

Original URL: https://blogs.msdn.microsoft.com/alejacma/2008/06/27/security-warning-dialog-box-is-displayed-when-you-try-to-silently-install-a-hotfix-or-an-update/
Post name: Security Warning dialog box is displayed when you try to silently install a hotfix or an update
Original author: Alejandro Campos Magencio
Posting date: 2008-06-27T05:27:00+00:00


Hi all,


You may be trying to install a hotfix or update silently, but you keep getting a security warning dialog because the file was downloaded from the Internet. The following article explains this situation: 889815 The Open File - Security Warning dialog box is displayed when you try to silently install a hotfix or an update by using a Visual Basic script in Windows XP Service Pack 2.


Attachment Execution Service (AES) is responsible for this dialog. KB 889815 suggests to use a script to set SEE_MASK_NOZONECHECKS environment variable before installing the hotfix or update. Well, this will work on VBScript, but may not work in other scenarios.


Alternatively you may set that environment variable in a batch job, but it may not help in your scenario either.


Are we out of luckthen? Well, not necessarily. Keep reading.


Run the following command on the file you downloaded from the Internet which contains the patch you want to install:

notepad patch.exe:Zone.Identifier

This will show us the Zone.Identifier Alternate Data Stream (ADS) of our file. We will see the following contents:

[ZoneTransfer]
ZoneId=3

Value 3 means that the file was downloaded from the Internet and it's potentially unsafe. This makes the warning dialog to appear. We may edit ZoneId value to make the warning disappear. A value of i.e. 2 may work in your environemnt. Change the value, save the ADS file and try installing the patch again.


This is a very good post to understand how Attachment Execution Service (AES) works and the effects of changing the ZoneId value: Demo of "Attachment Execution Service internals" in Windows XP SP2 and Windows Server 2003 SP1.


This is a list of some possible values we can use as ZoneId:


How Windows Knows that a File Is from the Internet: Manipulating Alternate Data Streams

NoZone = -1
MyComputer = 0
Intranet = 1
Trusted = 2
Internet = 3
Untrusted = 4

A value of6 may work for us, too.This value should be the same as resetting the checkbox "don't ask again" in the warning dialog.


I hope this helps.


Cheers,



Alex (Alejandro Campos Magencio)

Original URL: https://blogs.msdn.microsoft.com/alejacma/2008/06/25/how-to-sign-and-verify-the-signature-with-net-and-a-certificate-c/
Post name: How to Sign and Verify the signature with .NET and a certificate (C#)
Original author: Alejandro Campos Magencio
Posting date: 2008-06-25T05:55:00+00:00


Hi all,


Today I'm posting a sample which shows how to sign a text with a certificate in my Personal store (this cert will have public and private key associated to it) and how to verify that signature with a .cer file (for i.e. WinForms) applications or a client certificate (for i.e. ASP.NET) (both will onlyhave public key associated to them).

using System;
using System.Collections.Generic;
using System.Text;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;

namespace ConsoleApplication1
{
class Program
{
static byte[] Sign(string text, string certSubject)
{
// Access Personal (MY) certificate store of current user
X509Store my = new X509Store(StoreName.My, StoreLocation.CurrentUser);
my.Open(OpenFlags.ReadOnly);

// Find the certificate we'll use to sign
RSACryptoServiceProvider csp = null;
foreach (X509Certificate2 cert in my.Certificates)
{
if (cert.Subject.Contains(certSubject))
{
// We found it.
// Get its associated CSP and private key
csp = (RSACryptoServiceProvider)cert.PrivateKey;
}
}
if (csp == null)
{
throw new Exception("No valid cert was found");
}

// Hash the data
SHA1Managed sha1 = new SHA1Managed();
UnicodeEncoding encoding = new UnicodeEncoding();
byte[] data = encoding.GetBytes(text);
byte[] hash = sha1.ComputeHash(data);

// Sign the hash
return csp.SignHash(hash, CryptoConfig.MapNameToOID("SHA1"));
}

static bool Verify(string text, byte[] signature, string certPath)
{
// Load the certificate we'll use to verify the signature from a file
X509Certificate2 cert = new X509Certificate2(certPath);
// Note:
// If we want to use the client cert in an ASP.NET app, we may use something like this instead:
// X509Certificate2 cert = new X509Certificate2(Request.ClientCertificate.Certificate);

// Get its associated CSP and public key
RSACryptoServiceProvider csp = (RSACryptoServiceProvider)cert.PublicKey.Key;

// Hash the data
SHA1Managed sha1 = new SHA1Managed();
UnicodeEncoding encoding = new UnicodeEncoding();
byte[] data = encoding.GetBytes(text);
byte[] hash = sha1.ComputeHash(data);

// Verify the signature with the hash
return csp.VerifyHash(hash, CryptoConfig.MapNameToOID("SHA1"), signature);
}

static void Main(string[] args)
{
// Usage sample
try
{
// Sign text
byte[] signature = Sign("Test", "cn=my cert subject");

// Verify signature. Testcert.cer corresponds to "cn=my cert subject"
if (Verify("Test", signature, @"C:\testcert.cer"))
{
Console.WriteLine("Signature verified");
}
else
{
Console.WriteLine("ERROR: Signature not valid!");
}
}
catch (Exception ex)
{
Console.WriteLine("EXCEPTION: " + ex.Message);
}
Console.ReadKey();
}
}
}


I hope this helps.


Cheers,



Alex (Alejandro Campos Magencio)

Original URL: https://blogs.msdn.microsoft.com/alejacma/2008/06/20/system-directoryservices-directorysynchronization-returns-access-denied-with-non-admin-users/
Post name: System.DirectoryServices.DirectorySynchronization returns access denied with non-admin users
Original author: Alejandro Campos Magencio
Posting date: 2008-06-20T03:46:00+00:00


Hi all,


You may get an Access Denied error (COMException0x80070005) when using System.DirectoryServices.DirectorySynchronization in your .NET application with a non-admin user, but everything works fine with a domain administrator.


This issue will happen if we use DirectorySynchronization this way:

DirectorySearcher directorySearcher = new DirectorySearcher(rootPath);
directorySearcher.DirectorySynchronization = new DirectorySynchronization();

If we want to run this code as it is, we need to pass administrative credentials. If we are using standard user credentials we need to pass the right Flag saying that this is a normal user who do not have all the rights over Active Directory.


To understand this in detail please see this article which talks about the flags we can pass to DirectorySynchronization constructor:


DirectorySynchronizationOptions Enumeration


"
- ObjectSecurity: If this flag is not present, the caller must have the right to replicate changes. If this flag is present, the caller requires no rights, but is allowed to see only objects and attributes that are accessible to the caller.
"


So modify your code to use DirectorySynchronization inthis way:

directorySearcher.DirectorySynchronization = new DirectorySynchronization(DirectorySynchronization.ObjectSecurity);

Code should not fail with Access Denied error anymore. Now a standard user will have access to all the objects that she usually has access to.



I hope this helps.


Regards,



Alex (Alejandro Campos Magencio)

Original URL: https://blogs.msdn.microsoft.com/alejacma/2008/06/10/wmi-diag-wont-work-well-in-non-english-windows/
Post name: WMI Diag won’t work well in non-English Windows
Original author: Alejandro Campos Magencio
Posting date: 2008-06-10T06:40:00+00:00


Hi all,

If youever useWMI Diag script (The WMI Diagnosis Utility -- Version 2.0) on a non-English version of Windows (i.e. Spanish, French, Italian, German...), you will get tons of errors when the scriptchecks out default permissions on WMI namespaces or DCOM components related to WMI, for instance.

The cause is simple: the script checks permissions for groups of users which name is language-dependant.

If we use WMI Diag in i.e. a Spanish Windows, we will have to edit the script and replace:

- "BUILTIN\Administrators" with "BUILTIN\Administradores",

- "Everyone"with "Todos",

- "NT AUTHORITY\NETWORK SERVICE" with "NT AUTHORITY\Servicio de red",

- "NT AUTHORITY\LOCAL SERVICE" with "NT AUTHORITY\SERVICIO LOCAL",

- "NT AUTHORITY\Authenticated Users" with "NT AUTHORITY\Usuarios autentificados",

 

Now you can run the script and find out if your WMI is really broken.

I hope this helps.

Cheers,

 

Alex (Alejandro Campos Magencio)