Sunday, November 25, 2012

Comparing X509 distinguished names with BouncyCastle

In this post I am going to show how to compare X509 distinguished name using BouncyCastle. Distinguished names are used to specify the subject and issuer identity in X509 certificate. Distinguished name(DN) is like a LDAP directory name and contains one or more relative distinguished name(RDN) separated by comma. The definition for distinguished name can be found in X500 specification.

The problem with comparing distinguished name is the relative distinguished names they contain can be in any order. So simple string comparison will not work and parsing the distinguished name is not straight forward.

But BouncyCastle provides a class named X509Name through which we can easily parse and compare the X509 distinguished names. The below code snippets demos the parsing and comparison of X509 distinguished names
static void Main(string[] args)
{
    var name1 = new X509Name("CN=person1, OU=dept1, O=org1");
    var name1Dup = new X509Name("O=org1, OU=dept1, CN=person1");
    var name2 = new X509Name("CN=person2, OU=dept2, O=org1");

    Console.WriteLine("name1 = {0}", name1);
    Console.WriteLine("name2Dup = {0}", name1Dup);
    Console.WriteLine("name2 = {0}", name2);
    Console.WriteLine();

    Console.WriteLine("name1 == name1Dup => {0}", name1.Equivalent(name1Dup));
    Console.WriteLine("name1 == name2 => {0}", name1.Equivalent(name2));
}
and the output
name1 = CN=person1,OU=dept1,O=org1
name2Dup = O=org1,OU=dept1,CN=person1
name2 = CN=person2,OU=dept2,O=org1

name1 == name1Dup => True
name1 == name2 => False
The X509Name class makes it so simple to parse and manipulate the X509 distinguished names. But I encountered a situation where one of the relative distinguished name contained by X509 distinguished name is not recognizable by X509Name even though the underlying OID(object identifier) of the relative distinguished name is supported by the X509Name. The problematic relative distinguished name is "dnQualifier" whose OID is 2.5.4.46. The same OID is supported and parsable by X509Name if the relative distinguished name is "DN" instead "dnQualifier".

Digging little deep into X509Name source reveals that we can make it to parse/support "dnQualifier" relative distinguished name like below

static void Main(string[] args)
{
    X509Name.DefaultLookup["dnqualifier"] = X509Name.DnQualifier;

    var name1 = new X509Name("CN=person1, OU=dept1, O=org1, dnQualifier=aaaabbbbccccddddeeeeffffggg=");
    Console.WriteLine(name1);
}
In the above code basically we are providing another name("dnQualifier") for X509Name.DnQualifier which is by default identified with name "DN".

Executing plink from non-interactive shell

Today I had a requirement to launch plink.exe(a command-line interface to the PuTTY back ends) from a C# code and this code can run as Windows service or from an ASP.NET application. I accomplished the task with the following code
System.Diagnostics.Process.Start(PLINK_PATH_WITH_PARAMETERS);
The above line launches the plink program which I can see running in TaskManager but for some reason it is not connecting with the remote host. After some google search and experimentation with plink I finally found the reason why it is waiting and not connecting with the remote program.

Actually the plink was launched in non-interactive shell(as it is launched from Windows service/ASP.NET) and it runs under SYSTEM/ASP.NET user account. As we don't usually run plink in these user accounts plink sees the remote host's certificate as new unauthorized certificate and asking us to authorize it. As it is non-interactive shell we don't see the console and the authorization request.

After finding this I found that launching plink from another batch file with the following command line automatically answers "yes" to the plink's certificate authorization request and plink successfully able to execute the commands on remote host.
echo yes | C:\path\to\plink.exe {parameters}

Wednesday, September 19, 2012

Exporting RSA public key in PKCS#1 format

Recently I was working on task in which I had to generate a RSA key pair and export the public key to another application in PEM format. I implemented the task with help of BouncyCastle(code below) but the exported public key is not accepted by the other application.
static void ExportPublicKey(AsymmetricKeyParameter publicKey)
{
    var stringWriter = new StringWriter();
    var pemWriter = new PemWriter(stringWriter);
    pemWriter.WriteObject(publicKey);
    stringWriter.Flush();
    stringWriter.Close();

    File.WriteAllText(@"PublicKey.pem", stringWriter.ToString());
}
Little investigation revealed that the other application expects the public key in PKCS#1 format whereas the above code exports in PKCS#8 format(the ASN.1 structure of SubjectPublicKeyInfo). The difference between these formats is the additional field algorithm identifier in PKCS#8 format. We can clearly in there ASN.1 structure below

Also the exported PEM will have different start/end line like below

in PKCS#8
-----BEGIN PUBLIC KEY-----
...
-----END PUBLIC KEY-----
but in PKCS#1
-----BEGIN RSA PUBLIC KEY-----
...
-----END RSA PUBLIC KEY-----
Though the difference is one additional information but exporting public key without that information is not straightforward in BouncyCastle, or atleast at the time of writing. In OpenSSL(libcrypto) this is as simple as the calling the functions PEM_write_RSAPublicKey or PEM_write_bio_RSAPublicKey. In BouncyCastle the following code exports the public key in PKCS#1 format

static void ExportRsaPublicKey(AsymmetricKeyParameter publicKey)
{
    var subjectPublicKeyInfo = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(publicKey);
    var rsaPublicKeyStructure = RsaPublicKeyStructure.GetInstance(subjectPublicKeyInfo.GetPublicKey());
    var rsaPublicKeyPemBytes = Base64.Encode(rsaPublicKeyStructure.GetEncoded());

    var stringBuilder = new StringBuilder();

    stringBuilder.AppendLine("-----BEGIN RSA PUBLIC KEY-----");

    for (int i = 0; i < rsaPublicKeyPemBytes.Length; ++i)
    {
        stringBuilder.Append((char)rsaPublicKeyPemBytes[i]);

        // wraps after 64 column
        if (((i + 1) % 64) == 0)
            stringBuilder.AppendLine();
    }

    stringBuilder.AppendLine();
    stringBuilder.AppendLine("-----END RSA PUBLIC KEY-----");

    File.WriteAllText(@"RsaPublicKey.pem", stringBuilder.ToString());
}
and the code that generates RSA key pair is
static void Main(string[] args)
{
    var rsaKeyPairGenerator = new RsaKeyPairGenerator();
    rsaKeyPairGenerator.Init(new KeyGenerationParameters(new SecureRandom(), 2048));
    var keyPair = rsaKeyPairGenerator.GenerateKeyPair();

    ExportPublicKey(keyPair.Public);
    ExportRsaPublicKey(keyPair.Public);
}

Sunday, September 16, 2012

Constructing .NET RSACryptoServiceProvider from DER bytes

In my current task I have to construct private key object from its DER bytes. In OpenSSL I can easily do this with d2i_RSAPrivateKey function but in .NET this doesn't seems to be an easy task. I hoped in BouncyCastle this can be done in single method call but it requires the following code to achieve the functionality

byte[] privateKeyDer = File.ReadAllBytes("PrivateKey.der");
var derSequence = new Asn1InputStream(privateKeyDer).ReadObject();
var privateKeyStructure = new RsaPrivateKeyStructure((Asn1Sequence)derSequence);

var privateCrtKeyParameters = 
    new RsaPrivateCrtKeyParameters(privateKeyStructure.Modulus,
                                   privateKeyStructure.PublicExponent,
                                   privateKeyStructure.PrivateExponent,
                                   privateKeyStructure.Prime1,
                                   privateKeyStructure.Prime2,
                                   privateKeyStructure.Exponent1,
                                   privateKeyStructure.Exponent2,
                                   privateKeyStructure.Coefficient);

var privateKey = DotNetUtilities.ToRSA(privateCrtKeyParameters); // returns RSA object
Please note the classes Asn1InputStream, RsaPrivateKeyStructure, RsaPrivateCrtKeyParameters and DotNetUtilities are provided by BouncyCastle.

03-Nov-2013 UPDATE:
I recently realized that it is possible for the RSA components(e.g. modulus) to have lesser bits than the actual RSA key's bit size. For example, in one case the modulus is 255 bytes(2040 bits) instead of expected 256 bytes for a 2048 bits RSA key. Some validation code inside RSACryptoServiceProvider.ImportParameters method rejects these kind of RSA key parameters with exception "Invalid Parameter" as the bytes size is lesser than expected. I don't think it is a problem with BouncyCastle's BigInteger implementation as OpenSSL also encodes these big integers with fewer bytes like the BouncyCastle. But OpenSSL accepts these big integers without any issues but it is only the RSACryptoServicer.ImportParameters method that rejects it.

We can make the ImportParameters to work with these kind of big integers by padding zeros to the big integers. You can find the implementation below, so instead of calling DotNetUtilities.ToRSA() we should call our method ToRsa() to convert the RSA key parameters to RSA object.

private static byte[] PadLeft(byte[] bytes, int sizeToPad)
{
    if (bytes.Length < sizeToPad)
    {
        // byte default value is zero, so the paddedBytes array is filled with zero by default
        var paddedBytes = new byte[sizeToPad];

        Buffer.BlockCopy(bytes, 0, paddedBytes, sizeToPad - bytes.Length, bytes.Length);
        bytes = paddedBytes;
    }
    
    return bytes;
}

public static System.Security.Cryptography.RSA ToRsa(RsaPrivateCrtKeyParameters privateKey, int bitSize)
{
    var rsaParameters = new System.Security.Cryptography.RSAParameters();
    rsaParameters.Modulus = PadLeft(privateKey.Modulus.ToByteArrayUnsigned(), bitSize / 8);
    rsaParameters.Exponent = PadLeft(privateKey.PublicExponent.ToByteArrayUnsigned(), 3);
    rsaParameters.D = PadLeft(privateKey.Exponent.ToByteArrayUnsigned(), bitSize / 8);
    rsaParameters.P = PadLeft(privateKey.P.ToByteArrayUnsigned(), bitSize / 16);
    rsaParameters.Q = PadLeft(privateKey.Q.ToByteArrayUnsigned(), bitSize / 16);
    rsaParameters.DP = PadLeft(privateKey.DP.ToByteArrayUnsigned(), bitSize / 16);
    rsaParameters.DQ = PadLeft(privateKey.DQ.ToByteArrayUnsigned(), bitSize / 16);
    rsaParameters.InverseQ = PadLeft(privateKey.QInv.ToByteArrayUnsigned(), bitSize / 16);

    var rsa = new System.Security.Cryptography.RSACryptoServiceProvider();
    rsa.ImportParameters(rsaParameters);

    return rsa;
}

Saturday, April 07, 2012

Scripting Notepad++ with Python

In this post I am going explain how Notepad++ can be scripted with Python. I came to know about this as I wanted to analyse huge amount of console logs.

Installing Notepad++ Python Plugin

First we need to install Notepad++ Python plugin to able to control Notepad++ from python code. The plugin can be installed through Notepad++'s Plugin Manager by installing "Python Script" plugin or we can download the plugin from here http://sourceforge.net/projects/npppythonscript/ and extract the files into Notepad++'s plugin directory. As of this writing the Python Script plugin version is 0.9.2.

Invoking Python Scripts

The Notepad++ Python scripts needs to placed in particular directory so that it will recognized by the Python plugin and can be invoked from Notepad++. Usually the directory is %APPDATA%\Notepad++\plugins\config\PythonScript. The scripts can be invoked through menu Plugins->Python Script->Scripts. We can also create toolbar button for these scripts to quickly invoke them.

Counting Words Programmatically

To demonstrate the plugin lets write python script to count the number of characters, words and lines in the current editor window of Notepad++.
from Npp import *
import re

numChars = 0
numWords = 0
numLines = 0

editorContent = editor.getText()
for line in editorContent.splitlines():
  numLines += 1
  for word in re.findall("[a-zA-Z0-9]+", line):
    numWords += 1
    numChars += len(word)

notepad.messageBox("Number of characters: %d \nNumber of words: %d \nNumber of lines: %d" % (numChars, numWords, numLines))
at line 8 we get the active editor window's text content and everything else is typical Python program except at line 15 we tell the number of chars, words and lines through Notepad++ message box.

Bookmarking Programmatically

Lets see an another Python script which utilizes the bookmark feature of Notepad++
from Npp import *

notepad.menuCommand(MENUCOMMAND.SEARCH_CLEAR_BOOKMARKS)
linesBookmarked = []

def onMatch(lineNumber, match):
  if lineNumber not in linesBookmarked:
    lineStartPos = editor.positionFromLine(lineNumber)
    editor.gotoPos(lineStartPos)
    notepad.menuCommand(MENUCOMMAND.SEARCH_TOGGLE_BOOKMARK)
    linesBookmarked.append(lineNumber)

editor.pysearch("Pos", onMatch)
the above script bookmarks all the lines that contains the word "Pos". The Editor class provides a method "pysearch" which can search for given regular expression and will call the given function for each match. Like the "pysearch" method the Editor and Notepad class object provides various helper methods to automate Notepad++ functionalities from Python script.

Update on 02 July 2016
I came to know that the above script is not working in the latest version of Python Script plugin(thanks to Robbin Harrell). Upon investigating I realized there were many backward incompatible changes introduced in the recent versions of Python Script plugin. The below is the updated version of the script that works with Python Script 1.0.6.0. As I no longer use Microsoft Windows or Notepad++ on daily basis, I might not able to realize any backward incompatible changes in Python Script and keep the script up to date. So please let me if the script doesn't work for you, I will try to fix it and keep it up to date.
from Npp import *
 
notepad.menuCommand(MENUCOMMAND.SEARCH_CLEAR_BOOKMARKS)
linesBookmarked = []
 
def onMatch(match):
  lineNumber = editor.lineFromPosition(match.start())
  if lineNumber not in linesBookmarked:
    lineStartPos = editor.positionFromLine(lineNumber)
    editor.gotoPos(lineStartPos)
    notepad.menuCommand(MENUCOMMAND.SEARCH_TOGGLE_BOOKMARK)
    linesBookmarked.append(lineNumber)
 
editor.research("Pos", onMatch)

Sunday, March 04, 2012

Handling pre-shutdown notification in C# Windows service

In this post I am going to explain how pre-shutdown notification can be enabled and handled in C# Windows service.

The need for pre-shutdown notification
Starting from Windows Vista on wards Windows provides an mechanism to notify applications/services about the system shutdown/reboot. Though shutdown notification was already supported through ServiceBase class's CanShutdown property and OnShutdown method their functionality is very limited.

The limitation of OnShutdown method is, limited time given for the cleanup work and there is no guarantee that other essential services(e.g. DB, EventLog) are running. The last point is the fundamental reason why Microsoft brought this pre-shutdown notification.

Enabling pre-shutdown notification
If we are developing a Win32 application it is really easy to enable pre-shutdown notification. All we need to do is include "SERVICE_ACCEPT_PRESHUTDOWN" flag in dwControlsAccepted field of service's SERVICE_STATUS structure.

But in .NET's ServiceBase class there is no direct way to enable pre-shutdown notification. We can achieve the goal by accessing the ServiceBase class's internals through .NET reflection.
const int SERVICE_ACCEPT_PRESHUTDOWN = 0x100;
const int SERVICE_CONTROL_PRESHUTDOWN = 0xf;

MyService
{
  ...

  FieldInfo acceptedCommandsFieldInfo =
      typeof(ServiceBase).GetField("acceptedCommands", BindingFlags.Instance | BindingFlags.NonPublic);
  if (acceptedCommandsFieldInfo == null)
    throw ApplicationException("acceptedCommands field not found");
    
  int value = (int)acceptedCommandsFieldInfo.GetValue(this);
  acceptedCommandsFieldInfo.SetValue(this, value | SERVICE_ACCEPT_PRESHUTDOWN);
}
In the constructor of the service "MyService" we add the "SERVICE_ACCEPT_PRESHUTDOWN" flag to "acceptedCommands" private field of ServiceBase using reflection. This enables the pre-shutdown notification.

Handling pre-shutdown notification
The pre-shutdown notification is delivered through the ServiceBase class's "OnCustomCommand" method. This method is called whenever a command is sent to the service which is not supported by ServiceBase. The method provides a parameter "command" which holds the command code. So to handle the pre-shutdown notification we need to check whether the "command" matches with pre-shutdown notification code.
protected override void OnCustomCommand(int command)
{
    if (command == SERVICE_CONTROL_PRESHUTDOWN)
    {
      // do the clean-up here
    }
    else
        base.OnCustomCommand(command);
}
So that is all we need to enable and handle pre-shutdown notification.