809 lines
30 KiB
C#
809 lines
30 KiB
C#
using System;
|
|
using System.IO;
|
|
using System.Xml;
|
|
using System.Security;
|
|
using System.Security.Cryptography;
|
|
using System.Security.Cryptography.Xml;
|
|
using System.Data;
|
|
|
|
//TESTING
|
|
//already have: using System;
|
|
using System.Text;
|
|
//already have: using System.IO;
|
|
using Org.BouncyCastle.Security;
|
|
using Org.BouncyCastle.Crypto;
|
|
using Org.BouncyCastle.OpenSsl;
|
|
|
|
|
|
|
|
|
|
|
|
namespace GroundZero.KeyCodes
|
|
{
|
|
/// <summary>
|
|
/// AyaNova .net key generator
|
|
/// </summary>
|
|
public class KeyGen
|
|
{
|
|
private string _RegisteredTo;
|
|
|
|
private int _ScheduleableUsers;
|
|
|
|
System.DateTime _Expires;
|
|
|
|
private bool _RequestedTrial;
|
|
System.DateTime _InstallableUntil;
|
|
private bool _Lite;//case 1172
|
|
|
|
private DataTable dtPlugins;
|
|
|
|
//case 2094
|
|
private bool _LockOut;
|
|
System.DateTime _LockOutDate;
|
|
|
|
public KeyGen()
|
|
{
|
|
_Expires = System.DateTime.Today;
|
|
_InstallableUntil = System.DateTime.Today.AddDays(31);
|
|
WillExpire = false;
|
|
_LockOut = false;
|
|
}
|
|
|
|
public bool WillExpire { get; set; }
|
|
public string SelectedLicenseType { get; set; }
|
|
|
|
public string RegisteredTo
|
|
{
|
|
get
|
|
{
|
|
return _RegisteredTo;
|
|
}
|
|
set
|
|
{
|
|
_RegisteredTo = value;
|
|
}
|
|
}
|
|
|
|
public int ScheduleableUsers
|
|
{
|
|
get
|
|
{
|
|
return _ScheduleableUsers;
|
|
}
|
|
set
|
|
{
|
|
_ScheduleableUsers = value;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
public DateTime Expires
|
|
{
|
|
get
|
|
{
|
|
return _Expires;
|
|
}
|
|
set
|
|
{
|
|
_Expires = value;
|
|
}
|
|
}
|
|
|
|
public DateTime LockoutDate
|
|
{
|
|
get
|
|
{
|
|
return _LockOutDate;
|
|
}
|
|
set
|
|
{
|
|
_LockOutDate = value;
|
|
}
|
|
}
|
|
|
|
public bool LockOut
|
|
{
|
|
get
|
|
{
|
|
return _LockOut;
|
|
}
|
|
set
|
|
{
|
|
_LockOut = value;
|
|
}
|
|
}
|
|
|
|
|
|
public DateTime InstallableUntil
|
|
{
|
|
get
|
|
{
|
|
return _InstallableUntil;
|
|
}
|
|
set
|
|
{
|
|
_InstallableUntil = value;
|
|
}
|
|
}
|
|
|
|
//case 1172
|
|
public bool Lite
|
|
{
|
|
get
|
|
{
|
|
return _Lite;
|
|
}
|
|
set
|
|
{
|
|
_Lite = value;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
public bool RequestedTrial
|
|
{
|
|
get
|
|
{
|
|
return _RequestedTrial;
|
|
}
|
|
set
|
|
{
|
|
_RequestedTrial = value;
|
|
}
|
|
}
|
|
|
|
public DataTable Plugins
|
|
{
|
|
get
|
|
{
|
|
|
|
return dtPlugins;
|
|
}
|
|
set
|
|
{
|
|
dtPlugins = value;
|
|
}
|
|
|
|
}
|
|
|
|
/// <summary>
|
|
/// Generate a key in selected mode
|
|
/// </summary>
|
|
/// <param name="XMLMode"></param>
|
|
/// <returns></returns>
|
|
public string Generate(bool XMLMode)
|
|
{
|
|
if (XMLMode)
|
|
return GenerateXML();
|
|
else
|
|
return GenerateJS();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Generate XML keycode based on passed in data
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public string GenerateXML()
|
|
{
|
|
if (_RegisteredTo == null || _RegisteredTo == "")
|
|
throw new ArgumentException("RegisteredTo is required", "RegisteredTo");
|
|
|
|
System.Text.StringBuilder sb = new System.Text.StringBuilder();
|
|
|
|
System.Xml.XmlTextWriter w = new System.Xml.XmlTextWriter(new StringWriter(sb));
|
|
w.Formatting = System.Xml.Formatting.Indented;
|
|
|
|
w.WriteStartDocument(true);
|
|
//w.WriteDocType("KeyDocument",null,null,null);
|
|
double dSchemaVersion = 7;
|
|
if (_Lite)
|
|
w.WriteStartElement("AyaNovaLiteLicenseKey");
|
|
else
|
|
w.WriteStartElement("AyaNovaLicenseKey");
|
|
|
|
w.WriteElementString("SchemaVersion", XmlConvert.ToString(dSchemaVersion));
|
|
|
|
w.WriteElementString("Created", XmlConvert.ToString(System.DateTime.Now, XmlDateTimeSerializationMode.Local));
|
|
|
|
//case 2094
|
|
//all licenses are now subscriptions
|
|
w.WriteElementString("Sub", XmlConvert.ToString(true));
|
|
|
|
//case 2094
|
|
//TrialExpire
|
|
|
|
w.WriteElementString("RegisteredTo", _RegisteredTo);
|
|
|
|
//case 3187 - Source here
|
|
//rockfish
|
|
//var buffer = new Buffer('Rockfish - IP: ' + req.ip + ' USER: ' + req.apitoken.id);
|
|
w.WriteElementString("Source", ToHexString("KeyGen - USER: " + System.Environment.UserName +
|
|
" MACHINE: " + System.Environment.UserDomainName));
|
|
|
|
|
|
w.WriteElementString("InstallableUntil", XmlConvert.ToString(_InstallableUntil, XmlDateTimeSerializationMode.Local));
|
|
w.WriteElementString("TotalScheduleableUsers", XmlConvert.ToString(_ScheduleableUsers));
|
|
//if(!System.DateTime.Today.Date.Equals(_Expires.Date))
|
|
|
|
//case 2094 always has an expiry date now
|
|
w.WriteElementString("Expires", XmlConvert.ToString(_Expires.Date, XmlDateTimeSerializationMode.Local));
|
|
//case 2094 now has a separate hard stop date for ayanova to stop entirely
|
|
//used for licensed and web requested trials
|
|
if (_LockOut)
|
|
w.WriteElementString("LockDate", XmlConvert.ToString(_LockOutDate.Date, XmlDateTimeSerializationMode.Local));
|
|
|
|
//case 2094 all plugins now
|
|
//w.WriteElementString("FeatureWebBrowserInterface",XmlConvert.ToString(_FeatureWebInterface));
|
|
//w.WriteElementString("FeatureMBIInterface", XmlConvert.ToString(_FeatureMBIInterface));
|
|
w.WriteElementString("RequestedTrial", XmlConvert.ToString(_RequestedTrial));
|
|
|
|
|
|
|
|
//plugins
|
|
w.WriteStartElement("Plugins");
|
|
foreach (DataRow dr in dtPlugins.Rows)
|
|
{
|
|
w.WriteStartElement("Plugin");
|
|
w.WriteElementString("Item", dr["Plugin"].ToString());
|
|
//w.WriteElementString("Version",dr["Version"].ToString());
|
|
|
|
//case 2094
|
|
DateTime dtTemp = DateTime.Parse(dr["SubscriptionExpires"].ToString());
|
|
w.WriteElementString("SubscriptionExpires", XmlConvert.ToString(dtTemp, XmlDateTimeSerializationMode.Local));
|
|
|
|
w.WriteEndElement();
|
|
|
|
}
|
|
|
|
w.WriteEndElement();
|
|
|
|
w.WriteEndElement();
|
|
w.WriteEndDocument();
|
|
|
|
w.Flush();
|
|
w.Close();
|
|
|
|
|
|
// Load the license request file.
|
|
XmlDocument xmldoc = new XmlDocument();
|
|
try
|
|
{
|
|
|
|
xmldoc.LoadXml(sb.ToString());
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
return (ex.Message + ":\r\n\r\n" + sb.ToString());
|
|
}
|
|
|
|
// Get the key pair from the key store.
|
|
|
|
CspParameters parms = new CspParameters(1); // PROV_RSA_FULL
|
|
parms.Flags = CspProviderFlags.UseMachineKeyStore; // Use Machine store
|
|
parms.KeyContainerName = "AyaNovaLicenseContainer"; // "CodeProject" container
|
|
parms.KeyNumber = 2; // AT_SIGNATURE
|
|
try
|
|
{
|
|
RSACryptoServiceProvider csp = new RSACryptoServiceProvider(parms);
|
|
|
|
// Creating the XML signing object.
|
|
SignedXml sxml = new SignedXml(xmldoc);
|
|
sxml.SigningKey = csp;
|
|
|
|
// Set the canonicalization method for the document.
|
|
sxml.SignedInfo.CanonicalizationMethod =
|
|
SignedXml.XmlDsigCanonicalizationUrl; // No comments.
|
|
|
|
// Create an empty reference (not enveloped) for the XPath
|
|
// transformation.
|
|
Reference r = new Reference("");
|
|
|
|
// Create the XPath transform and add it to the reference list.
|
|
r.AddTransform(new XmlDsigEnvelopedSignatureTransform(false));
|
|
|
|
// Add the reference to the SignedXml object.
|
|
sxml.AddReference(r);
|
|
|
|
// Compute the signature.
|
|
sxml.ComputeSignature();
|
|
|
|
// Get the signature XML and add it to the document element.
|
|
XmlElement sig = sxml.GetXml();
|
|
xmldoc.DocumentElement.AppendChild(sig);
|
|
|
|
// Write-out formatted signed XML to console (allow for redirection).
|
|
System.Text.StringBuilder sbFinal = new System.Text.StringBuilder();
|
|
XmlTextWriter writer = new XmlTextWriter(new StringWriter(sbFinal));
|
|
writer.Formatting = Formatting.Indented;
|
|
|
|
try
|
|
{
|
|
xmldoc.WriteTo(writer);
|
|
}
|
|
finally
|
|
{
|
|
writer.Flush();
|
|
writer.Close();
|
|
}
|
|
|
|
|
|
return sbFinal.ToString();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
return (ex.Message + ":\r\n\r\n" + sb.ToString());
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/// <summary>
|
|
/// Generate keycode based on passed in data
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public string GenerateJS()
|
|
{
|
|
if (_RegisteredTo == null || _RegisteredTo == "")
|
|
throw new ArgumentException("RegisteredTo is required", "RegisteredTo");
|
|
|
|
try
|
|
{
|
|
|
|
StringBuilder sbKey = new StringBuilder();
|
|
StringWriter sw = new StringWriter(sbKey);
|
|
|
|
#region ## BUILD JSON
|
|
using (Newtonsoft.Json.JsonWriter w = new Newtonsoft.Json.JsonTextWriter(sw))
|
|
{
|
|
w.Formatting = Newtonsoft.Json.Formatting.Indented;
|
|
|
|
//outer object start
|
|
w.WriteStartObject();
|
|
|
|
if (_Lite)
|
|
w.WritePropertyName("AyaNovaLiteLicenseKey");
|
|
else
|
|
w.WritePropertyName("AyaNovaLicenseKey");
|
|
|
|
w.WriteStartObject();//start of key object
|
|
|
|
w.WritePropertyName("SchemaVersion");
|
|
w.WriteValue("7");
|
|
|
|
//stamp a unique value in the key so it can be revoked later
|
|
//used to use the digest value of the key for this with xml key
|
|
//whole unix timestamp seconds but kept as a double to work beyond 2038
|
|
w.WritePropertyName("Id");
|
|
var vv = Math.Truncate((DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1))).TotalSeconds);
|
|
string sId = vv.ToString();
|
|
if (sId.Contains(","))
|
|
sId = sId.Split('.')[0];
|
|
w.WriteValue(sId);
|
|
|
|
w.WritePropertyName("Created");
|
|
w.WriteValue(System.DateTime.Now);
|
|
|
|
w.WritePropertyName("Sub");
|
|
w.WriteValue("true");
|
|
|
|
w.WritePropertyName("RegisteredTo");
|
|
w.WriteValue(_RegisteredTo);//unicode test string
|
|
|
|
|
|
//case 3187 - Source here
|
|
//rockfish
|
|
//var buffer = new Buffer('Rockfish - IP: ' + req.ip + ' USER: ' + req.apitoken.id);
|
|
w.WritePropertyName("Source");
|
|
w.WriteValue(ToHexString("KeyGen - USER: " + System.Environment.UserName +
|
|
" MACHINE: " + System.Environment.UserDomainName));
|
|
|
|
|
|
w.WritePropertyName("InstallableUntil");
|
|
w.WriteValue(_InstallableUntil);
|
|
|
|
w.WritePropertyName("TotalScheduleableUsers");
|
|
w.WriteValue(_ScheduleableUsers.ToString());//Needs to be a string to match rockfish format
|
|
|
|
w.WritePropertyName("Expires");
|
|
w.WriteValue(_Expires.Date);
|
|
|
|
if (_LockOut)
|
|
{
|
|
w.WritePropertyName("LockDate");
|
|
w.WriteValue(_LockOutDate.Date);
|
|
|
|
}
|
|
|
|
w.WritePropertyName("RequestedTrial");
|
|
w.WriteValue(_RequestedTrial.ToString());
|
|
|
|
//PLUGINS
|
|
w.WritePropertyName("Plugins");
|
|
w.WriteStartObject();//start of key object
|
|
w.WritePropertyName("Plugin");
|
|
w.WriteStartArray();
|
|
|
|
foreach (DataRow dr in dtPlugins.Rows)
|
|
{
|
|
//----PLUGIN------
|
|
w.WriteStartObject();
|
|
|
|
w.WritePropertyName("Item");
|
|
w.WriteValue(dr["Plugin"].ToString());
|
|
|
|
DateTime dtTemp = DateTime.Parse(dr["SubscriptionExpires"].ToString());
|
|
w.WritePropertyName("SubscriptionExpires");
|
|
w.WriteValue(dtTemp);
|
|
|
|
w.WriteEndObject();
|
|
//----------------
|
|
}
|
|
|
|
|
|
//end of plugins array
|
|
w.WriteEnd();
|
|
|
|
//end of plugins object
|
|
w.WriteEndObject();
|
|
|
|
//end of AyaNova/AyaNovaLite key object
|
|
w.WriteEndObject();
|
|
|
|
//close outer 'wrapper' object brace }
|
|
w.WriteEndObject();
|
|
|
|
}//end of using statement
|
|
#endregion build json
|
|
|
|
#region ## CALCULATE SIGNATURE
|
|
|
|
//GET JSON as a string with whitespace stripped outside of delimited strings
|
|
//http://stackoverflow.com/questions/8913138/minify-indented-json-string-in-net
|
|
string keyNoWS = System.Text.RegularExpressions.Regex.Replace(sbKey.ToString(), "(\"(?:[^\"\\\\]|\\\\.)*\")|\\s+", "$1");
|
|
|
|
|
|
//**** Note this is our real 2016 private key
|
|
var privatePEM = @"-----BEGIN RSA PRIVATE KEY-----
|
|
MIIEpAIBAAKCAQEAz7wrvLDcKVMZ31HFGBnLWL08IodYIV5VJkKy1Z0n2snprhSi
|
|
u3izxTyz+SLpftvKHJpky027ii7l/pL9Bo3JcjU5rKrxXavnE7TuYPjXn16dNLd0
|
|
K/ERSU+pXLmUaVN0nUWuGuUMoGJMEXoulS6pJiG11yu3BM9fL2Nbj0C6a+UwzEHF
|
|
mns3J/daZOb4gAzMUdJfh9OJ0+wRGzR8ZxyC99Na2gDmqYglUkSMjwLTL/HbgwF4
|
|
OwmoQYJBcET0Wa6Gfb17SaF8XRBV5ZtpCsbStkthGeoXZkFriB9c1eFQLKpBYQo2
|
|
DW3H1MPG2nAlQZLbkJj5cSh7/t1bRF08m6P+EQIDAQABAoIBAQCGvTpxLRXgB/Kk
|
|
EtmQBEsMx9EVZEwZeKIqKuDsBP8wvf4/10ql5mhT6kehtK9WhSDW5J2z8DtQKZMs
|
|
SBKuCZE77qH2CPp9E17SPWzQoRbaW/gDlWpYhgf8URs89XH5zxO4XtXKw/4omRlV
|
|
zLYiNR2pifv0EHqpOAg5KGzewdEo4VgXgtRWpHZLMpH2Q0/5ZIKMhstI6vFHP1p7
|
|
jmU4YI6uxiu7rVrZDmIUsAGoTdMabNqK/N8hKaoBiIto0Jn1ck26g+emLg8m160y
|
|
Xciu5yFUU+PP1SJMUs+k1UnAWf4p46X9jRLQCBRue9o0Ntiq/75aljRoDvgdwDsR
|
|
mg4ZANqxAoGBAPBoM5KoMZ4sv8ZFv8V+V8hgL5xiLgGoiwQl91mRsHRM/NQU5A/w
|
|
tH8nmwUrJOrksV7kX9228smKmoliTptyGGyi1NPmSkA7cN9YYnENoOEBHCVNK9vh
|
|
P+bkbMYUDNMW4fgOj09oXtQtMl5E2B3OTGoNwZ2w13YQJ8RIniLPsX7nAoGBAN01
|
|
eQNcUzQk9YrFGTznOs8udDLBfigDxaNnawvPueulJdBy6ZXDDrKmkQQA7xxl8YPr
|
|
dNtBq2lOgnb6+smC15TaAfV/fb8BLmkSwdn4Fy0FApIXIEOnLq+wjkte98nuezl8
|
|
9KXDzaqNI9hPuk2i36tJuLLMH8hzldveWbWjSlRHAoGBAKRPE7CQtBjfjNL+qOta
|
|
RrT0yJWhpMANabYUHNJi+K8ET2jEPnuGkFa3wwPtUPYaCABLJhprB9Unnid3wTIM
|
|
8RSO1ddd9jGgbqy3w9Bw+BvQnmQAMpG9iedNB+r5mSpM4XSgvuIO+4EYwuwbMXpt
|
|
nVx+um4Eh75xnDxTRYGVYkLRAoGAaZVpUlpR+HSfooHbPv+bSWKB4ewLPCw4vHrT
|
|
VErtEfW8q9b9eRcmP81TMFcFykc6VN4g47pfh58KlKHM7DwAjDLWdohIy89TiKGE
|
|
V3acEUfv5y0UoFX+6ara8Ey+9upWdKUY3Lotw3ckoc3EPeQ84DQK7YSSswnAgLaL
|
|
mS/8fWcCgYBjRefVbEep161d2DGruk4X7eNI9TFJ278h6ydW5kK9aTJuxkrtKIp4
|
|
CYf6emoB4mLXFPvAmnsalkhN2iB29hUZCXXSUjpKZrpijL54Wdu2S6ynm7aT97NF
|
|
oArP0E2Vbow3JMxq/oeXmHbrLMLQfYyXwFmciLFigOtkd45bfHdrbA==
|
|
-----END RSA PRIVATE KEY-----";
|
|
|
|
PemReader pr = new PemReader(new StringReader(privatePEM));
|
|
AsymmetricCipherKeyPair keys = (AsymmetricCipherKeyPair)pr.ReadObject();
|
|
var encoder = new UTF8Encoding(false, true);
|
|
var inputData = encoder.GetBytes(keyNoWS);
|
|
var signer = SignerUtilities.GetSigner("SHA256WITHRSA");
|
|
signer.Init(true, keys.Private);
|
|
signer.BlockUpdate(inputData, 0, inputData.Length);
|
|
var sign = signer.GenerateSignature();
|
|
var signature = Convert.ToBase64String(sign);
|
|
|
|
#endregion calculate signature
|
|
|
|
#region ## Return the signed key
|
|
System.Text.StringBuilder sbOut = new StringBuilder();
|
|
//sbOut.AppendLine("=-=-=-=-=-=-< LICENSE KEYCODE >-=-=-=-=-=-=-=");
|
|
sbOut.AppendLine("[KEY");
|
|
sbOut.AppendLine(sbKey.ToString());
|
|
sbOut.AppendLine("KEY]");
|
|
sbOut.AppendLine("[SIGNATURE");
|
|
sbOut.AppendLine(signature);
|
|
sbOut.AppendLine("SIGNATURE]");
|
|
// sbOut.AppendLine("=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=");
|
|
return sbOut.ToString();
|
|
#endregion
|
|
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
return (ex.Message);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//************************************************************************************************************
|
|
//************************************************************************************************************
|
|
//*********************************** NEW 2016 JSON KEY WORK *************************************************
|
|
//************************************************************************************************************
|
|
//************************************************************************************************************
|
|
|
|
//GEN-TEST
|
|
|
|
/// <summary>
|
|
/// Figure out a javascript and c# compatible signed key scheme
|
|
/// Requirements:
|
|
/// 1) generate a new json key in windows and sign it, then validate and parse it to json in windows then validate and parse in linux
|
|
/// 2) generate a new json key in linux and sign it, then validate and parse it in linux then in windows
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public void GenTest()
|
|
{
|
|
jsonGenerate();
|
|
jsonVerify();
|
|
return;
|
|
}
|
|
|
|
|
|
// /gen-test
|
|
|
|
public void jsonGenerate()
|
|
{
|
|
StringBuilder sbKey = new StringBuilder();
|
|
StringWriter sw = new StringWriter(sbKey);
|
|
#region ## BUILD JSON
|
|
using (Newtonsoft.Json.JsonWriter w = new Newtonsoft.Json.JsonTextWriter(sw))
|
|
{
|
|
w.Formatting = Newtonsoft.Json.Formatting.Indented;
|
|
|
|
//outer object start
|
|
w.WriteStartObject();
|
|
|
|
w.WritePropertyName("AyaNovaLicenseKey");
|
|
w.WriteStartObject();//start of key object
|
|
|
|
w.WritePropertyName("SchemaVersion");
|
|
w.WriteValue("7");
|
|
|
|
w.WritePropertyName("Created");
|
|
w.WriteValue(System.DateTime.Now);
|
|
|
|
w.WritePropertyName("Sub");
|
|
w.WriteValue("true");
|
|
|
|
w.WritePropertyName("RegisteredTo");
|
|
w.WriteValue("Что такое Unicode?");//unicode test string
|
|
|
|
w.WritePropertyName("InstallableUntil");
|
|
w.WriteValue(System.DateTime.Now.AddMonths(1));
|
|
|
|
w.WritePropertyName("TotalScheduleableUsers");
|
|
w.WriteValue("20");
|
|
|
|
w.WritePropertyName("Expires");
|
|
w.WriteValue(System.DateTime.Now.AddYears(1));
|
|
|
|
w.WritePropertyName("RequestedTrial");
|
|
w.WriteValue("false");
|
|
|
|
//PLUGINS
|
|
w.WritePropertyName("Plugins");
|
|
w.WriteStartObject();//start of key object
|
|
w.WritePropertyName("Plugin");
|
|
w.WriteStartArray();
|
|
|
|
//----PLUGIN------
|
|
w.WriteStartObject();
|
|
w.WritePropertyName("Item");
|
|
w.WriteValue("QuickNotification");
|
|
w.WritePropertyName("SubscriptionExpires");
|
|
w.WriteValue(System.DateTime.Now.AddYears(1));
|
|
w.WriteEndObject();
|
|
//----------------
|
|
|
|
//----PLUGIN------
|
|
w.WriteStartObject();
|
|
w.WritePropertyName("Item");
|
|
w.WriteValue("RI - Responsive Interface");
|
|
w.WritePropertyName("SubscriptionExpires");
|
|
w.WriteValue(System.DateTime.Now.AddYears(1));
|
|
w.WriteEndObject();
|
|
//----------------
|
|
|
|
//----PLUGIN------
|
|
w.WriteStartObject();
|
|
w.WritePropertyName("Item");
|
|
w.WriteValue("ImportExportCSVDuplicate");
|
|
w.WritePropertyName("SubscriptionExpires");
|
|
w.WriteValue(System.DateTime.Now.AddYears(1));
|
|
w.WriteEndObject();
|
|
//----------------
|
|
|
|
//end of plugins array
|
|
w.WriteEnd();
|
|
|
|
//end of plugins object
|
|
w.WriteEndObject();
|
|
|
|
//end of AyaNova key object
|
|
w.WriteEndObject();
|
|
|
|
//close outer 'wrapper' object brace }
|
|
w.WriteEndObject();
|
|
|
|
}//end of using statement
|
|
#endregion build json
|
|
|
|
//TEST TEST TEST
|
|
//sbKey.Clear();
|
|
//sbKey.Append("data_data_data");
|
|
|
|
//## GET JSON as a string with whitespace stripped outside of delimited strings
|
|
//http://stackoverflow.com/questions/8913138/minify-indented-json-string-in-net
|
|
string keyNoWS = System.Text.RegularExpressions.Regex.Replace(sbKey.ToString(), "(\"(?:[^\"\\\\]|\\\\.)*\")|\\s+", "$1");
|
|
|
|
#region ## CALCULATE SIGNATURE
|
|
|
|
//**** Note this is our real 2016 private key
|
|
var privatePEM = @"-----BEGIN RSA PRIVATE KEY-----
|
|
MIIEpAIBAAKCAQEAz7wrvLDcKVMZ31HFGBnLWL08IodYIV5VJkKy1Z0n2snprhSi
|
|
u3izxTyz+SLpftvKHJpky027ii7l/pL9Bo3JcjU5rKrxXavnE7TuYPjXn16dNLd0
|
|
K/ERSU+pXLmUaVN0nUWuGuUMoGJMEXoulS6pJiG11yu3BM9fL2Nbj0C6a+UwzEHF
|
|
mns3J/daZOb4gAzMUdJfh9OJ0+wRGzR8ZxyC99Na2gDmqYglUkSMjwLTL/HbgwF4
|
|
OwmoQYJBcET0Wa6Gfb17SaF8XRBV5ZtpCsbStkthGeoXZkFriB9c1eFQLKpBYQo2
|
|
DW3H1MPG2nAlQZLbkJj5cSh7/t1bRF08m6P+EQIDAQABAoIBAQCGvTpxLRXgB/Kk
|
|
EtmQBEsMx9EVZEwZeKIqKuDsBP8wvf4/10ql5mhT6kehtK9WhSDW5J2z8DtQKZMs
|
|
SBKuCZE77qH2CPp9E17SPWzQoRbaW/gDlWpYhgf8URs89XH5zxO4XtXKw/4omRlV
|
|
zLYiNR2pifv0EHqpOAg5KGzewdEo4VgXgtRWpHZLMpH2Q0/5ZIKMhstI6vFHP1p7
|
|
jmU4YI6uxiu7rVrZDmIUsAGoTdMabNqK/N8hKaoBiIto0Jn1ck26g+emLg8m160y
|
|
Xciu5yFUU+PP1SJMUs+k1UnAWf4p46X9jRLQCBRue9o0Ntiq/75aljRoDvgdwDsR
|
|
mg4ZANqxAoGBAPBoM5KoMZ4sv8ZFv8V+V8hgL5xiLgGoiwQl91mRsHRM/NQU5A/w
|
|
tH8nmwUrJOrksV7kX9228smKmoliTptyGGyi1NPmSkA7cN9YYnENoOEBHCVNK9vh
|
|
P+bkbMYUDNMW4fgOj09oXtQtMl5E2B3OTGoNwZ2w13YQJ8RIniLPsX7nAoGBAN01
|
|
eQNcUzQk9YrFGTznOs8udDLBfigDxaNnawvPueulJdBy6ZXDDrKmkQQA7xxl8YPr
|
|
dNtBq2lOgnb6+smC15TaAfV/fb8BLmkSwdn4Fy0FApIXIEOnLq+wjkte98nuezl8
|
|
9KXDzaqNI9hPuk2i36tJuLLMH8hzldveWbWjSlRHAoGBAKRPE7CQtBjfjNL+qOta
|
|
RrT0yJWhpMANabYUHNJi+K8ET2jEPnuGkFa3wwPtUPYaCABLJhprB9Unnid3wTIM
|
|
8RSO1ddd9jGgbqy3w9Bw+BvQnmQAMpG9iedNB+r5mSpM4XSgvuIO+4EYwuwbMXpt
|
|
nVx+um4Eh75xnDxTRYGVYkLRAoGAaZVpUlpR+HSfooHbPv+bSWKB4ewLPCw4vHrT
|
|
VErtEfW8q9b9eRcmP81TMFcFykc6VN4g47pfh58KlKHM7DwAjDLWdohIy89TiKGE
|
|
V3acEUfv5y0UoFX+6ara8Ey+9upWdKUY3Lotw3ckoc3EPeQ84DQK7YSSswnAgLaL
|
|
mS/8fWcCgYBjRefVbEep161d2DGruk4X7eNI9TFJ278h6ydW5kK9aTJuxkrtKIp4
|
|
CYf6emoB4mLXFPvAmnsalkhN2iB29hUZCXXSUjpKZrpijL54Wdu2S6ynm7aT97NF
|
|
oArP0E2Vbow3JMxq/oeXmHbrLMLQfYyXwFmciLFigOtkd45bfHdrbA==
|
|
-----END RSA PRIVATE KEY-----";
|
|
|
|
PemReader pr = new PemReader(new StringReader(privatePEM));
|
|
AsymmetricCipherKeyPair keys = (AsymmetricCipherKeyPair)pr.ReadObject();
|
|
var encoder = new UTF8Encoding(false, true);
|
|
var inputData = encoder.GetBytes(keyNoWS);
|
|
var signer = SignerUtilities.GetSigner("SHA256WITHRSA");
|
|
signer.Init(true, keys.Private);
|
|
signer.BlockUpdate(inputData, 0, inputData.Length);
|
|
var sign = signer.GenerateSignature();
|
|
var signature = Convert.ToBase64String(sign);
|
|
|
|
#endregion calculate signature
|
|
|
|
//## Write out to file key and signature
|
|
System.Text.StringBuilder sbOut = new StringBuilder();
|
|
sbOut.AppendLine("=-=-=-=-=-=-< LICENSE KEYCODE >-=-=-=-=-=-=-=");
|
|
sbOut.AppendLine("[KEY");
|
|
sbOut.AppendLine(sbKey.ToString());
|
|
sbOut.AppendLine("KEY]");
|
|
sbOut.AppendLine("[SIGNATURE");
|
|
sbOut.AppendLine(signature);
|
|
sbOut.AppendLine("SIGNATURE]");
|
|
sbOut.AppendLine("=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=");
|
|
using (StreamWriter writer = new StreamWriter("c:\\temp\\newkey\\JSAyaLicense.txt", false, Encoding.UTF8))
|
|
{
|
|
writer.WriteLine(sbOut.ToString());
|
|
}
|
|
|
|
}//END OF JSONGENTEST METHOD
|
|
|
|
|
|
|
|
|
|
public bool jsonVerify()
|
|
{
|
|
string licenseFileData = string.Empty;
|
|
//using (StreamReader rdr = new StreamReader("c:\\temp\\newkey\\JSAyaLicense.txt", Encoding.UTF8))
|
|
using (StreamReader rdr = new StreamReader("c:\\temp\\newkey\\NODE_JSAyaLicense.txt", Encoding.UTF8))
|
|
{
|
|
licenseFileData = rdr.ReadToEnd();
|
|
}
|
|
|
|
//extract between [KEY and KEY]
|
|
if (!licenseFileData.Contains("[KEY") ||
|
|
!licenseFileData.Contains("KEY]") ||
|
|
!licenseFileData.Contains("[SIGNATURE") ||
|
|
!licenseFileData.Contains("SIGNATURE]"))
|
|
throw new System.FormatException("KEY IS NOT VALID! Missing one or more required delimiters");
|
|
|
|
string keyNoWS = System.Text.RegularExpressions.Regex.Replace(ExtractString(licenseFileData, "[KEY", "KEY]").Trim(), "(\"(?:[^\"\\\\]|\\\\.)*\")|\\s+", "$1");
|
|
string keySig = ExtractString(licenseFileData, "[SIGNATURE", "SIGNATURE]").Trim();
|
|
|
|
//***** NOTE: this is our real 2016 public key
|
|
var publicPem = @"-----BEGIN PUBLIC KEY-----
|
|
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAz7wrvLDcKVMZ31HFGBnL
|
|
WL08IodYIV5VJkKy1Z0n2snprhSiu3izxTyz+SLpftvKHJpky027ii7l/pL9Bo3J
|
|
cjU5rKrxXavnE7TuYPjXn16dNLd0K/ERSU+pXLmUaVN0nUWuGuUMoGJMEXoulS6p
|
|
JiG11yu3BM9fL2Nbj0C6a+UwzEHFmns3J/daZOb4gAzMUdJfh9OJ0+wRGzR8ZxyC
|
|
99Na2gDmqYglUkSMjwLTL/HbgwF4OwmoQYJBcET0Wa6Gfb17SaF8XRBV5ZtpCsbS
|
|
tkthGeoXZkFriB9c1eFQLKpBYQo2DW3H1MPG2nAlQZLbkJj5cSh7/t1bRF08m6P+
|
|
EQIDAQAB
|
|
-----END PUBLIC KEY-----";
|
|
|
|
|
|
|
|
PemReader pr = new PemReader(new StringReader(publicPem));
|
|
var KeyParameter = (Org.BouncyCastle.Crypto.AsymmetricKeyParameter)pr.ReadObject();
|
|
var signer = SignerUtilities.GetSigner("SHA256WITHRSA");
|
|
signer.Init(false, KeyParameter);
|
|
var expectedSig = Convert.FromBase64String(keySig);
|
|
var msgBytes = Encoding.UTF8.GetBytes(keyNoWS);
|
|
signer.BlockUpdate(msgBytes, 0, msgBytes.Length);
|
|
bool isValid = signer.VerifySignature(expectedSig);
|
|
|
|
return isValid;
|
|
|
|
}//end of jsonVerify test code
|
|
|
|
/// <summary>
|
|
/// Extract string between tokens
|
|
/// </summary>
|
|
/// <param name="s"></param>
|
|
/// <param name="openTag"></param>
|
|
/// <param name="closeTag"></param>
|
|
/// <returns></returns>
|
|
string ExtractString(string s, string openTag, string closeTag)
|
|
{
|
|
int startIndex = s.IndexOf(openTag) + openTag.Length;
|
|
int endIndex = s.IndexOf(closeTag, startIndex);
|
|
return s.Substring(startIndex, endIndex - startIndex);
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
|
|
//************************************************************************************************************
|
|
//************************************************************************************************************
|
|
//*********************************** NEW 2016 JSON KEY WORK *************************************************
|
|
//************************************************************************************************************
|
|
//************************************************************************************************************
|
|
|
|
|
|
public static string ToHexString(string str)
|
|
{
|
|
var sb = new StringBuilder();
|
|
|
|
var bytes = Encoding.Unicode.GetBytes(str);
|
|
foreach (var t in bytes)
|
|
{
|
|
sb.Append(t.ToString("X2"));
|
|
}
|
|
|
|
return sb.ToString(); // returns: "48656C6C6F20776F726C64" for "Hello world"
|
|
}
|
|
|
|
public static string FromHexString(string hexString)
|
|
{
|
|
var bytes = new byte[hexString.Length / 2];
|
|
for (var i = 0; i < bytes.Length; i++)
|
|
{
|
|
bytes[i] = Convert.ToByte(hexString.Substring(i * 2, 2), 16);
|
|
}
|
|
|
|
return Encoding.Unicode.GetString(bytes); // returns: "Hello world" for "48656C6C6F20776F726C64"
|
|
}
|
|
|
|
//End of module
|
|
}
|
|
}
|