Files
MyMcKesson/TomcatServer/ChoiceMSLConnect/SystemAccessVerifier.cs
2016-07-27 00:32:34 -04:00

281 lines
9.7 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ChoiceMSLConnect
{
/// <summary>
/// This class is copied (Stripped down to it's core, with all unneccessary stuff for this instance removed)
/// from Registration Server's SystemAccessVerifier.
/// All new code should go there. No Pin is generated here. The pin for a userkey
/// should always be generated at the registration server.
/// This class however can be used to convert a SystemApiKey to a UserApiKey, usefull for what we are
/// trying to do in this service
/// </summary>
internal class SystemAccessVerifier
{
#region Consts
const int SYSTEM_API_KEY_LENGTH = 22;
const int USER_API_KEY_LENGTH = 20;
const int PIN_LENGTH = 6;
const string SYSTEM_API_KEY_BEGIN_MARKER = "$";
const string SYSTEM_API_KEY_END_MARKER = "#";
internal static readonly string LETTER_CHARS = "AZXVGLTCIRKPNOMQJSHUFWDEYB";
internal static int GET_LETTER_CHARS_COUNT { get { return LETTER_CHARS.Length; } }
#endregion
#region System Api Key
private string _systemApiKey = String.Empty;
internal string SystemApiKey
{
get
{
return _systemApiKey;
}
set
{
if (ValidateSystemKey(value))
_systemApiKey = value.ToUpper().Trim();
}
}
private static bool ValidateSystemKey(string key)
{
if (!String.IsNullOrEmpty(key))
key = key.ToUpper().Trim();
// $247B2CB4A437EB74C62#M
if (!String.IsNullOrEmpty(key) && key.Length == SYSTEM_API_KEY_LENGTH &&
key[0] == Char.Parse(SYSTEM_API_KEY_BEGIN_MARKER) && key[SYSTEM_API_KEY_LENGTH - 2] == Char.Parse(SYSTEM_API_KEY_END_MARKER) &&
Char.IsLetter(key[SYSTEM_API_KEY_LENGTH - 1]))
{
// AllAreLettersOrDigit?
for (int i = 1; i < SYSTEM_API_KEY_LENGTH - 2; ++i)
{
if (!Char.IsLetterOrDigit(key[i]))
return false;
}
return true;
}
return false;
}
#endregion
#region User Api Key
private string _UserApiKey = String.Empty;
internal string UserApiKey
{
get
{
return _UserApiKey;
}
set
{
if (ValidateUserKey(value))
_UserApiKey = value.ToUpper().Trim();
}
}
private static bool ValidateUserKey(string key)
{
if (!String.IsNullOrEmpty(key))
key = key.ToUpper().Trim();
//247BQCB4A-37EB-4C62M
if (!String.IsNullOrEmpty(key) && key.Length == USER_API_KEY_LENGTH &&
Char.IsLetter(key[USER_API_KEY_LENGTH - 1]) &&
Char.IsLetter(key[4]) && key[9] == '-' && key[14] == '-')
{
// Perform Product Security check
char productType = key[USER_API_KEY_LENGTH - 1];
int v = (int)productType % GET_LETTER_CHARS_COUNT;
if (key[4] == LETTER_CHARS[v])
return true;
}
return false;
}
#endregion
#region Product Type
private char _productType = '\0';
internal char ProductType { get { return Char.ToUpper(_productType); } }
internal bool IsValidProductType { get { return (_productType != '\0'); } }
#endregion
#region Construction
internal SystemAccessVerifier(string userApiKey)
{
if (!String.IsNullOrEmpty(userApiKey))
userApiKey = userApiKey.ToUpper().Trim();
if (ValidateUserKey(userApiKey))
{
UserApiKey = userApiKey;
ConvertUserToSystemApiKey();
_productType = GetProductTypeFromSystemApiKey(SystemApiKey);
}
}
#endregion
#region Private Converters
private void ConvertUserToSystemApiKey()
{
if (ValidateUserKey(UserApiKey))
{
// 247BQCB4A-37EB-4C62M
StringBuilder sb = new StringBuilder(UserApiKey);
char productType = sb[USER_API_KEY_LENGTH - 1];
sb.Remove(USER_API_KEY_LENGTH - 1, 1);
// Add More Randomness into this (nobody will ever know :S)
// Dynamic Calc for 2 - 2, 12 - 4
int a = (int)'A';
int z = (int)'Z';
int ic = (int)sb[2];
if ((ic - 2 >= a) && (ic <= z))
sb[2] = (char)(ic - 2);
ic = sb[12];
if ((ic - 4 >= a) && (ic <= z))
sb[12] = (char)(ic - 4);
//Otherway arround arbitrary swap (just in case)
// Swap 3 to 10, and 5 to 16
char c = sb[3];
sb[3] = sb[10];
sb[10] = c;
c = sb[5];
sb[5] = sb[16];
sb[16] = c;
// Assign '-'
sb[4] = '-';
// How clever :S
string s = ReverseString(sb.ToString());
int n = 0;
sb = new StringBuilder(s);
for (int i = 0; i < s.Length; ++i)
{
if (s[i] == '-')
{
sb[i] = (s[n]);
n++;
}
else
{
sb[i] = (s[i]);
}
}
// $247B2CB4A437EB74C62#M
s = SYSTEM_API_KEY_BEGIN_MARKER + sb.ToString() + SYSTEM_API_KEY_END_MARKER + Char.ToUpper(productType);
SystemApiKey = s;
}
}
#endregion
#region Internal Statics
internal static char GetProductTypeFromSystemApiKey(string systemApiKey)
{
if (ValidateSystemKey(systemApiKey))
return Char.ToUpper(systemApiKey[SYSTEM_API_KEY_LENGTH - 1]);
else
return '\0';
}
#endregion
#region Private static Key Generation Helper Functions
private static string ReverseString(string str)
{
if (!String.IsNullOrEmpty(str))
{
Stack<char> stack = new Stack<char>();
foreach (char c in str)
stack.Push(c);
StringBuilder sb = new StringBuilder();
while (stack.Count > 0)
sb.Append(stack.Pop());
return sb.ToString();
}
return String.Empty;
}
/// <summary>
/// Perform checksum on string
/// </summary>
/// <param name="strAboutToBeChecksummed"></param>
/// <returns>Checksum</returns>
private static int PerformChecksum(string strAboutToBeChecksummed)
{
if (!String.IsNullOrEmpty(strAboutToBeChecksummed))
{
int nChecksum = 0;
for (int i = 0; i < strAboutToBeChecksummed.Length; ++i)
{
if (Char.IsDigit(strAboutToBeChecksummed[i]))
nChecksum = nChecksum + int.Parse(strAboutToBeChecksummed[i].ToString());
}
return nChecksum;
}
return 0;
}
/// <summary>
/// Dash a String every Nth Character
/// </summary>
/// <returns>a dashed string</returns>
private static string MakeIntoDashSeperatedString(string strAboutToBeDashed, int DashEveryNthCharacter)
{
if (!String.IsNullOrEmpty(strAboutToBeDashed))
{
StringBuilder sb = new StringBuilder();
for (int i = 0; i < strAboutToBeDashed.Length; i++)
{
if ((i != 0) && ((i % DashEveryNthCharacter) == 0))
sb.Append("-");
sb.Append(strAboutToBeDashed[i]);
}
return sb.ToString();
}
return String.Empty;
}
/// <summary>
/// Undash a String
/// </summary>
/// <returns>a string without dashes</returns>
private static string MakeIntoDashUnseperatedString(string strAboutToBeUndashed)
{
if (!String.IsNullOrEmpty(strAboutToBeUndashed))
return strAboutToBeUndashed.Replace("-", "");
return String.Empty;
}
/// <summary>
/// Check if the passed in string contains only digits
/// </summary>
/// <param name="strToCheckForDigits">string to check for digits for</param>
/// <returns>true, if all digits are numbers</returns>
private static bool ContainsOnlyDigits(string strToCheckForDigits)
{
if (!String.IsNullOrEmpty(strToCheckForDigits))
{
for (int i = 0; i < strToCheckForDigits.Length; ++i)
{
if (!Char.IsDigit(strToCheckForDigits[i]))
return false;
}
return true;
}
return false;
}
#endregion
}
}