- Custom fork of QZ Tray 2.2.x with certificate validation bypassed - Implemented pairing key (HMAC) authentication as replacement - Modified files: PrintSocketClient.java (certificate check disabled) - New files: PairingAuth.java, PairingConfigDialog.java - Excluded build artifacts (out/, lib/javafx*) from repository - Library JARs included for dependency management
81 lines
3.8 KiB
C#
81 lines
3.8 KiB
C#
// #########################################################
|
|
// # WARNING WARNING WARNING #
|
|
// #########################################################
|
|
// # #
|
|
// # This file is intended for demonstration purposes #
|
|
// # only. #
|
|
// # #
|
|
// # It is the SOLE responsibility of YOU, the programmer #
|
|
// # to prevent against unauthorized access to any signing #
|
|
// # functions. #
|
|
// # #
|
|
// # Organizations that do not protect against un- #
|
|
// # authorized signing will be black-listed to prevent #
|
|
// # software piracy. #
|
|
// # #
|
|
// # -QZ Industries, LLC #
|
|
// # #
|
|
// #########################################################
|
|
|
|
using System.Security.Cryptography;
|
|
using System.Security.Cryptography.X509Certificates;
|
|
using System.Text;
|
|
using System.Web.Services;
|
|
|
|
// To convert a .PEM PrivateKey:
|
|
// openssl pkcs12 -export -inkey private-key.pem -in digital-certificate.txt -out private-key.pfx
|
|
private static X509KeyStorageFlags STORAGE_FLAGS = X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.Exportable;
|
|
|
|
/**
|
|
* Note, this example is for .NET Forms/PageMethods
|
|
* For MVC, change the following:
|
|
*
|
|
* public ActionResult SignMessage() {
|
|
* string request = Request.QueryString["request"];
|
|
* ...
|
|
* return Content(base64, "text/plain");
|
|
* ...
|
|
* return SignMessage();
|
|
*
|
|
* ... and replace PageMethods calls with fetch("@Url.Content("./SignMessage/?request=")" + toSign
|
|
*/
|
|
[WebMethod]
|
|
public static string SignMessage(string request)
|
|
{
|
|
//var WEBROOT_PATH = HttpContext.Current.Server.MapPath("/");
|
|
//var CURRENT_PATH = HttpContext.Current.Server.MapPath("~");
|
|
//var PARENT_PATH = System.IO.Directory.GetParent(WEBROOT).Parent.FullName;
|
|
var KEY = "/path/to/private-key.pfx";
|
|
var PASS = "";
|
|
|
|
try
|
|
{
|
|
var cert = new X509Certificate2(KEY, PASS, STORAGE_FLAGS);
|
|
RSACryptoServiceProvider csp = (RSACryptoServiceProvider)cert.PrivateKey; // PFX defaults to the weaker "SHA1"
|
|
byte[] data = new ASCIIEncoding().GetBytes(request);
|
|
RSACryptoServiceProvider cspStrong = new RSACryptoServiceProvider(); // 2.1 and higher: Make RSACryptoServiceProvider that can handle SHA256, SHA512
|
|
cspStrong.ImportParameters(csp.ExportParameters(true)); // Copy to stronger RSACryptoServiceProvider
|
|
byte[] hash = new SHA512CryptoServiceProvider().ComputeHash(data); // Use SHA1CryptoServiceProvider for QZ Tray 2.0 and older
|
|
string base64 = Convert.ToBase64String(cspStrong.SignHash(hash, CryptoConfig.MapNameToOID("SHA512"))); // Use "SHA1" for QZ Tray 2.0 and older
|
|
return base64;
|
|
|
|
/*
|
|
* // Or per https://stackoverflow.com/a/50104158/3196753
|
|
* var cert = new X509Certificate2(KEY, PASS, STORAGE_FLAGS);
|
|
* var csp = cert.GetRSAPrivateKey();
|
|
* byte[] data = new ASCIIEncoding().GetBytes(request);
|
|
* return Convert.ToBase64String(csp.SignData(data, HashAlgorithmName.SHA512, RSASignaturePadding.Pkcs1)); // Use "SHA1" for QZ Tray 2.0 and older
|
|
*/
|
|
}
|
|
catch(Exception ex)
|
|
{
|
|
if((STORAGE_FLAGS & X509KeyStorageFlags.MachineKeySet) == X509KeyStorageFlags.MachineKeySet)
|
|
{
|
|
// IISExpress may fail with "Invalid provider type specified"; remove MachineKeySet flag, try again
|
|
STORAGE_FLAGS = STORAGE_FLAGS & ~X509KeyStorageFlags.MachineKeySet;
|
|
return SignMessage(request);
|
|
}
|
|
throw ex;
|
|
}
|
|
}
|