Skip to content

Instantly share code, notes, and snippets.

@lennybacon
Last active August 29, 2015 13:57
Show Gist options
  • Save lennybacon/9661030 to your computer and use it in GitHub Desktop.
Save lennybacon/9661030 to your computer and use it in GitHub Desktop.
Sanitizing Strings according to Windows Client Certificate Enrollment Protocol [MS-WCCE]
public static partial class StringExtensions
{
/// <summary>
/// Sanitizes the string according to Windows Client Certificate Enrollment
/// Protocol: http://msdn.microsoft.com/en-us/library/cc249879.aspx
/// </summary>
/// <param name="input">The input.</param>
/// <returns>System.String.</returns>
/// <remarks>
/// All disallowed characters in the original name MUST be replaced with
/// the appropriate replacements values as specified in section
/// 3.1.1.4.1.1.2: http://msdn.microsoft.com/en-us/library/cc249743.aspx.
/// The sanitized name MUST be truncated to no more than 51 characters in
/// total length. The truncated name MUST NOT exceed 51 characters. If an
/// incomplete sanitized character sequence remains at the end of the
/// string (for example, !002 instead of !0023), the incomplete sequence
/// MUST be truncated completely.
/// The characters that were removed or truncated from the sanitized string
/// in the preceding bulleted item MUST be hashed according to the rules
/// specified in section 3.1.1.4.1.1.1. The resultant hash MUST be
/// converted to a 5-character string. The string MUST be five characters
/// in total length and MUST be padded with leading zeros on the left to
/// ensure a total length of five characters.
/// A minus sign (–) MUST be appended to the truncated sanitized name
/// followed by the 5-character string that contains the hash value.
/// </remarks>
public static string ToWcceSanitizedString(this string input)
{
var sanitizedString = string.Empty;
var hashString = string.Empty;
var exclusions =
new List<char>
{
'!',
'"',
'#',
'%',
'&',
'\'',
'(',
')',
'*',
'+',
',',
'/',
':',
';',
'<',
'=',
'>',
'?',
'[',
'\\',
']',
'^',
'`',
'{',
'|',
'}',
};
foreach (var c in input)
{
var charCode = (int)c;
if (charCode >= 0x20 &&
charCode <= 0x7F &&
exclusions.IndexOf(c) == -1)
{
if (sanitizedString.Length + 1 > 51)
{
hashString = hashString + c;
continue;
}
sanitizedString = sanitizedString + c;
continue;
}
if (sanitizedString.Length + 5 > 51)
{
hashString = hashString + "!00" + charCode.ToString("X2");
continue;
}
sanitizedString = sanitizedString + "!00" + charCode.ToString("X2");
}
if (!string.IsNullOrWhiteSpace(hashString))
{
UInt16 hashSeed = 0;
const ushort value = 0x8000;
foreach (var c in hashString)
{
var lowBit = (UInt16)(((value & hashSeed) != 0) ? 1 : 0);
hashSeed = (UInt16)(((hashSeed << 1) | lowBit) + c);
}
sanitizedString +=
"-" +
hashSeed.ToString(CultureInfo.InvariantCulture).PadLeft(5, '0');
}
return sanitizedString.ToLowerInvariant();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment