cleaning structure

This commit is contained in:
Quality System Admin
2025-10-16 01:42:59 +03:00
parent e0ba349862
commit 50c791e242
469 changed files with 1016 additions and 29776 deletions

Binary file not shown.

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg id="svg4208" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" height="128" width="128" version="1.1" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" viewBox="0 0 128.00001 128.00001">
<metadata id="metadata4213">
<rdf:RDF>
<cc:Work rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>
<dc:title/>
</cc:Work>
</rdf:RDF>
</metadata>
<g id="layer1" transform="translate(-125.25 -253.66)">
<path id="XMLID_48_" d="m253.07 310.83v2.3662l-0.78875 3.9437-5.5211 32.338-65.465 30.761v-41.014c0-5.5212-2.3662-11.042-5.5212-14.197l-0.78873-0.78874-49.69-46.535 73.352-22.085 48.113 40.226 0.78875 0.78875c3.1549 3.1549 5.5211 7.8874 5.5211 14.197z" fill="#44aa53"/>
<path id="rect3864" d="m172.93 304.22 46.535-15.775 11.042 8.6761-46.535 17.352-11.042-10.254z" fill="#2a6831"/>
<path id="path3860" d="m161.58 270.6" fill="none"/>
<path id="XMLID_47_" d="m182.08 308.46 37.071-13.408s0-22.085-22.085-34.704l-36.282 11.042c0.78873 0 22.873 14.197 21.296 37.071z" fill="#fff"/>
<path id="XMLID_45_" d="m156.84 339.22" fill="#597239"/>
<path id="XMLID_37_" d="m181.29 338.92v41.32l-43.977-34.169-11.994-68.337 50.373 46.882 0.79958 0.79461c2.3987 2.3839 4.7974 7.9462 4.7974 13.508z" fill="#2a6831"/>
<path id="XMLID_35_" d="m181.29 380.24z" fill="#597239"/>
<polygon id="XMLID_5_" points="425.9 74 425.9 74" fill="#597239" transform="matrix(7.8874 0 0 7.8874 -3177.9 -203.43)"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 361 KiB

View File

@@ -0,0 +1,33 @@
N
q812;four inch width for 203dpi printer
Q1218,26;six inch height for 203dpi printer
B5,26,0,1A,3,7,152,B,"0001"
A310,26,0,3,1,1,N,"SKU 00001 MFG 0001"
A310,56,0,3,1,1,N,"QZ-Tray Java Application"
A310,86,0,3,1,1,N,"TEST PRINT SUCCESSFUL"
A310,116,0,3,1,1,N,"FROM SAMPLE.HTML"
A310,146,0,3,1,1,N,"EDIT EPL_MULTIPLES.TXT"
P1,1
N
q812
Q1218,26
B5,26,0,1A,3,7,152,B,"0002"
A310,26,0,3,1,1,N,"SKU 00002 MFG 0002"
A310,56,0,3,1,1,N,"QZ-Tray Java Application"
A310,86,0,3,1,1,N,"TEST PRINT SUCCESSFUL"
A310,116,0,3,1,1,N,"FROM SAMPLE.HTML"
A310,146,0,3,1,1,N,"EDIT EPL_MULTIPLES.TXT"
P1,1
N
q812
Q1218,26
B5,26,0,1A,3,7,152,B,"0003"
A310,26,0,3,1,1,N,"SKU 00003 MFG 0003"
A310,56,0,3,1,1,N,"QZ-Tray Java Application"
A310,86,0,3,1,1,N,"TEST PRINT SUCCESSFUL"
A310,116,0,3,1,1,N,"FROM SAMPLE.HTML"
A310,146,0,3,1,1,N,"EDIT EPL_MULTIPLES.TXT"
P1,1

View File

@@ -0,0 +1,11 @@
N
q812
Q1218,26; q and Q values edited to reflect 4x6 inch size at 203 dpi
B5,26,0,1A,3,7,152,B,"1234"
A310,26,0,3,1,1,N,"SKU 00000 MFG 0000"
A310,56,0,3,1,1,N,"QZ-Tray Java Application"
A310,86,0,3,1,1,N,"TEST PRINT SUCCESSFUL"
A310,116,0,3,1,1,N,"FROM SAMPLE.HTML"
A310,146,0,3,1,1,N,"EDIT EPL_SAMPLE.TXT"
P1,1

Binary file not shown.

View File

@@ -0,0 +1,25 @@
<n><DA><RL><RC300,20><F12>BOCA <F6><RC100,40>
<NR><RC290,110><RL><F6><HW1,1>PROM=
<RC300,160><RL><HW1,1><VA7><RC370,740><RU>GHOSTWRITER
<RC48,880><RR><F2>FRIENDLY GHOST LANGUAGE
<RC52,862>PLACE LETTERS ANYWHERE
<RC80,1170><F6><RR>VOID
<RC15,1100><F3>TEST TICKET ONLY
<RC8,1010><X2><NXL10>*GHOST 123*<RR>
<RC78,915> CODE 39
<RU><RC320,740><BS17,30>TICKET & LABEL PRINTER
<NR><F3><RC0,300>EXCELLENT PRINT QUALITY
<NR><RC30,300> Print any bar code
<RC70,300><X2><OL6>^CODE 128^
<RC90,250><RR>CODE 128
<RC96,340><X3><NXP10>*MONKEY*
<RC206,340><X2><NP6>*MONKEY*
<F2><HW1,1><NR><F1><SP180,640><LO1>
<RC371,385><F2><NR>SW1= SW2= SW3=<RC371,824>LEFT = 1 RIGHT = 0
<RC385,150><F11>Script printing is now standard.
<RC430,150><F9>High density printing is clear and readable
<RC450,150><F2>High density printing is clear and readable
<RC470,150><F1>Legal size printing
<RC0,100><LT4><VX1200>
<p>


Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

View File

@@ -0,0 +1,12 @@
~CREATE;DATAMATRIX;144
SCALE;DOT;300;300
ALPHA
POINT;50;100;16;9;*Printed using QZ Tray*
STOP
BARCODE
DATAMATRIX;XD16;C20;R20;ECC200;ID5;150;150
*0100000123000017*
STOP
END
~EXECUTE;DATAMATRIX;1
~NORMAL

View File

@@ -0,0 +1,23 @@
AA1V01678H0812
PS%0H0040V01510FW02H0735
%2H200V1590P02RDB@1,057,056,SATO
%0H0040V01076FW02H0735
%2H0353V01215P02RDB@0,026,025,BEST BEFORE
%2H0761V01215P02RDB@0,026,025,BATCH/LOT
%2H0761V01370P02RDB@0,026,025,CONTENT
%2H0761V01489P02RDB@0,026,025,SSCC
%2H0758V01590P02RDB@1,057,056,Product
%2H0777V01669P02RDB@0,057,056,
%2H0761V01183P02RDB@0,061,062,223344
%2H0589V00109P02RDB@1,038,037,(00)038312345600000018
%2H0741V01052BG04256>I>F0203831234560087370001
%2H0719V00374BG04256>I>F00038312345600000018
%2H0617V00786P02RDB@1,038,037,(02)03831234560087(37)0001
%2H0139V01370P02RDB@0,026,025,COUNT
%2H0139V01344P02RDB@0,061,062,0001
%2H0761V01344P02RDB@0,061,062,03831234560087
%2H0761V01463P02RDB@1,061,062,038312345600000018
%2H0675V00697BG04240>I>F1525052010223344
%2H0559V00443P02RDB@1,038,037,(15)250520(10)223344
%2H0355V01182P02RDB@0,061,062,20.05.25
Q1Z

View File

@@ -0,0 +1,38 @@
#
# Echoes the signed message and exits
# usage: R sign-message.R "test"
#
#########################################################
# 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 #
# #
#########################################################
library(openssl)
mykey <- "private-key.pem"
# Treat command line argument as message to be signed
message <- enc2utf8(commandArgs(trailingOnly = TRUE))
# Load the private key
key <- read_key(file = mykey, password = mypass)
# Create the signature
sig <- signature_create(serialize(message, NULL), hash = sha512, key = key) # Use hash = sha1 for QZ Tray 2.0 and older
print(sig)

View File

@@ -0,0 +1,50 @@
<%
'#########################################################
'# 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 #
'# #
'#########################################################
Option Explicit
Dim rsa, pem, sig, data, glob, success, password
' New unlock method for Chilkat - Unregistered version, only good for 30 days
Set glob = Server.CreateObject("Chilkat_9_5_0.Global")
success = glob.UnlockBundle("Anything for 30-day trial")
If (success <> 1) Then
Response.Write "<pre>" & Server.HTMLEncode(glob.LastErrorText) & "</pre>"
Response.End
End If
' ActiveX library http://www.chilkatsoft.com/
Set pem = CreateObject("Chilkat_9_5_0.Pem")
Set rsa = CreateObject("Chilkat_9_5_0.Rsa")
data = request("request")
password = ""
success = pem.LoadPemFile("private-key.pem", password)
If (success <> 1) Then
Response.Write "<pre>" & Server.HTMLEncode(pem.LastErrorText) & "</pre>"
Response.End
End If
rsa.ImportPrivateKey(pem.GetPrivateKey(0).getXml())
rsa.EncodingMode = "base64"
sig = rsa.SignStringENC(data, "SHA-512") ' Use "SHA-1" for QZ Tray 2.0 and older
Response.ContentType = "text/plain"
Response.Write Server.HTMLEncode(sig)
%>

View File

@@ -0,0 +1,67 @@
// #########################################################
// # 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;
using System.Text;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.OpenSsl;
using Org.BouncyCastle.Security;
// Public method for signing the input string with the private key
// ===============================================================
string privateKey = "private-key.pem"; // PKCS#8 PEM file
string SignMessage(string msg)
{
// Convert the input string to a byte array
byte[] input = Encoding.ASCII.GetBytes(msg);
// Initialize the signer with the algorithm and the private key
ISigner sig = SignerUtilities.GetSigner("SHA512withRSA");
sig.Init(true, getPrivateKey());
// Generate signature and return it as a base64 string
sig.BlockUpdate(input, 0, input.Length);
return Convert.ToBase64String(sig.GenerateSignature());
}
AsymmetricKeyParameter getPrivateKey()
{
using (var reader = System.IO.File.OpenText(privateKey))
{
var pem = new PemReader(reader).ReadObject();
return pem as AsymmetricKeyParameter ?? (pem as AsymmetricCipherKeyPair).Private;
}
}
// Public method for returning the certificate
// ===========================================
string certificate = "digital-certificate.txt";
string GetCertificate()
{
using (var reader = System.IO.File.OpenText(certificate))
{
return reader.ReadToEnd();
}
}

View File

@@ -0,0 +1,73 @@
/*
* ColdFusion signing example
* Echoes the signed message and exits
*/
// #########################################################
// # 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 #
// # #
// #########################################################
<cfset signature = sign("private-key.pem", url.request)>
<cfcontent type="text/plain">
<cfoutput>#signature#</cfoutput>
<cfscript>
/**
* Sign the given string
* @keyPath Path to PEM formatted private key
* @message message to be signed
* @encoding I am the encoding used when returning the signature (base64 by default).
* @output false
*/
public any function sign(required string keyPath, required string message, string algorithm = "SHA512withRSA", string encoding = "base64") {
// Note: change algorithm to "SHA1withRSA" for QZ Tray 2.0 and older
createObject("java", "java.security.Security")
.addProvider(createObject("java", "org.bouncycastle.jce.provider.BouncyCastleProvider").init());
privateKey = createPrivateKey(fileRead(expandPath(keyPath)));
var signer = createObject("java", "java.security.Signature").getInstance(javaCast( "string", algorithm ));
signer.initSign(privateKey);
signer.update(charsetDecode(message, "utf-8"));
var signedBytes = signer.sign();
return encoding == "binary" ? signedBytes : binaryEncode(signedBytes, encoding);
}
/**
* Set the private key using the provided pem formatted content.
*
* @contents PEM key contents
* @output false
*/
private any function createPrivateKey(required string contents) {
var pkcs8 = createObject("java", "java.security.spec.PKCS8EncodedKeySpec").init(
binaryDecode(stripKeyDelimiters(contents), "base64")
);
return createObject("java", "java.security.KeyFactory")
.getInstance(javaCast( "string", "RSA" )).generatePrivate(pkcs8);
}
/**
* Strip X509 cert delimiters
*
* @keyText PEM formatted key data
* @output false
*/
private string function stripKeyDelimiters(required string keyText) {
return trim(reReplace(keyText, "-----(BEGIN|END)[^\r\n]+", "", "all" ));
}
</cfscript>

View File

@@ -0,0 +1,54 @@
/*
* Salesforce APEX Signing Example
* Returns the signed message to a wired controller
*/
// #########################################################
// # 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 #
// # #
// #########################################################
public with sharing class SignMessage {
@AuraEnabled(cacheable = true)
public static String signMessage(String toSign){
String privateKeyBase64 = '<private-key.pem content without header or footer>';
Blob sig = Crypto.sign('RSA-SHA512',
Blob.valueOf(toSign),
EncodingUtil.base64Decode(privateKeyBase64));
return EncodingUtil.base64Encode(sig);
}
}
/** JavaScript - Adjust as needed
import signMessage from '@salesforce/apex/SignMessage.signMessage';
@wire(signMessage)
qz.security.setSignatureAlgorithm("SHA512");
qz.security.setSignaturePromise(function(toSign) {
return function (resolve, reject) {
try {
resolve(signMessage({toSign : toSign}));
} catch(err) {
reject(err);
}
}
});
**/

View File

@@ -0,0 +1,53 @@
// #########################################################
// # 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;
public IActionResult Index(string request)
{
var KEY = "/path/to/private-key.pfx";
var PASS = "";
try
{
byte[] data = new ASCIIEncoding().GetBytes(request);
var cert = new X509Certificate2(KEY, PASS, STORAGE_FLAGS);
RSA rsa = (RSA)cert.GetRSAPrivateKey();
var signed = rsa.SignData(data, HashAlgorithmName.SHA512, RSASignaturePadding.Pkcs1);
string base64 = Convert.ToBase64String(signed);
return Content(base64);
}
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 Index(request);
}
throw ex;
}
}

View File

@@ -0,0 +1,80 @@
// #########################################################
// # 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;
}
}

View File

@@ -0,0 +1,99 @@
/*
* Echos the signed message
*/
// #########################################################
// # 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 #
// # #
// #########################################################
/* Steps:
* 1. Convert private key to golang compatible format:
* openssl rsa -in private-key.pem -out private-key-updated.pem
*/
package main
import (
"crypto"
"crypto/rand"
"crypto/rsa"
"crypto/sha1"
"crypto/x509"
"encoding/base64"
"encoding/pem"
"fmt"
"io/ioutil"
"net/http"
)
var privateKey = "C:\\path\\to\\private-key-updated.pem"
var password = "S3cur3P@ssw0rd"
var listenPort = ":8080"
func main() {
http.HandleFunc("/", handler)
http.ListenAndServe(listenPort, nil)
}
func handler(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Access-Control-Allow-Origin", "*")
w.Header().Add("Content-Type", "text/plain")
rsaPrivateKey, err := decodeKey(privateKey)
if err != nil {
displayError(w, "Error reading key", err)
return
}
data := r.URL.Query().Get("request")
if len(data) < 1 {
displayError(w, "Request cannot be blank", err)
return
}
hash := sha1.Sum([]byte(data))
rng := rand.Reader
signature, err := rsa.SignPKCS1v15(rng, rsaPrivateKey, crypto.SHA512, hash[:]) // Use crypto.SHA1 for QZ Tray 2.0 and older
if err != nil {
displayError(w, "Error from signing: %s\n", err)
return
}
fmt.Fprintf(w, base64.StdEncoding.EncodeToString(signature))
}
func displayError(w http.ResponseWriter, msg string, err error) {
w.WriteHeader(http.StatusInternalServerError)
fmt.Fprintf(w, "500 - Internal Server Error\n\n"+msg+"\n\nDetails:\n", err)
}
func decodeKey(path string) (*rsa.PrivateKey, error) {
b, err := ioutil.ReadFile(path)
if err != nil {
return nil, err
}
block, _ := pem.Decode(b)
if x509.IsEncryptedPEMBlock(block) {
der, err := x509.DecryptPEMBlock(block, []byte(password))
if err != nil {
return nil, err
}
return x509.ParsePKCS1PrivateKey(der)
}
return x509.ParsePKCS1PrivateKey(block.Bytes)
}

View File

@@ -0,0 +1,143 @@
// package foo.bar;
/*
* Java signing example
* Echoes the signed message and exits
*/
// #########################################################
// # 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 #
// # #
// #########################################################
import java.io.*;
import java.security.*;
import java.security.spec.*;
import java.util.Base64;
import java.util.logging.*;
/**
* Utility for creating an RSA SHA1 signature based on a supplied PEM formatted private key
*/
public class MessageSigner {
private static Logger logger = Logger.getLogger(MessageSigner.class.getName());
private Signature sig;
/**
* Standard Java usage example, safe to remove
*/
public static void main(String args[]) throws Exception {
if (args.length < 2) {
logger.severe("Usage:\nMessageSigner.class [path to private key] [data to sign]\n");
System.exit(1);
}
byte[] key = MessageSigner.readFile(args[0]);
String toSign = args[1];
MessageSigner ms = new MessageSigner(key);
String signature = ms.sign(toSign);
logger.log(Level.INFO, "Request: {0}", toSign);
logger.log(Level.INFO, "Response: {0}", signature);
}
/**
* Servlet usage example, safe to remove
*
protected void doProcessRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// Get request from URL
String data = request.getParameter("request");
String signature = new MessageSigner("private-key.pem").sign(data);
// Send signed message back
response.setContentType("text/plain");
PrintWriter out = response.getWriter();
out.write(signature);
out.flush();
out.close();
}
/**
* Constructs an RSA SHA1 signature object for signing
* @param keyData
* @throws Exception
*/
public MessageSigner(byte[] keyData) throws Exception {
// Warning: PKCS#8 required. If PKCS#1 (RSA) key is provided convert using:
// $ openssl pkcs8 -topk8 -inform PEM -outform PEM -in private-key.pem -out private-key-pkcs8.pem -nocrypt
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(parseKeyData(keyData));
KeyFactory kf = KeyFactory.getInstance("RSA");
PrivateKey key = kf.generatePrivate(keySpec);
sig = Signature.getInstance("SHA512withRSA"); // Use "SHA1withRSA" for QZ Tray 2.0 and older
sig.initSign(key);
}
/**
* Signs the specified data with the provided private key, returning the
* RSA SHA1 signature
* @param data Message to sign
* @return Base64 encoded signature
* @throws Exception
*/
public String sign(String data) throws Exception {
sig.update(data.getBytes());
return Base64.getEncoder().encodeToString(sig.sign());
}
/**
* Reads the raw byte[] data from a file resource
* @param path File path to read
* @return the raw byte data from file
* @throws IOException
*/
public static byte[] readFile(String path) throws IOException {
InputStream is = MessageSigner.class.getResourceAsStream(path);
if (is == null) {
throw new IOException(String.format("Can't open resource \"%s\"", path));
}
DataInputStream dis = new DataInputStream(is);
byte[] data = new byte[dis.available()];
dis.readFully(data);
dis.close();
return data;
}
/**
* Parses a base64 encoded private key by stripping the header and footer lines
* @param keyData PEM file contents
* @return Raw key byes
* @throws IOException
*/
private static byte[] parseKeyData(byte[] keyData) throws IOException {
StringBuilder sb = new StringBuilder();
String[] lines = new String(keyData).split("[\r?\n]+");
String[] skips = new String[]{"-----BEGIN", "-----END", ": "};
for (String line : lines) {
boolean skipLine = false;
for (String skip : skips) {
if (line.contains(skip)) {
skipLine = true;
}
}
if (!skipLine) {
sb.append(line.trim());
}
}
return Base64.getDecoder().decode(sb.toString());
}
}

View File

@@ -0,0 +1,89 @@
/*
* JavaScript client-side example using jsrsasign
*/
// #########################################################
// # 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 #
// # #
// #########################################################
/**
* Depends:
* - jsrsasign-latest-all-min.js
* - qz-tray.js
*
* Steps:
*
* 1. Include jsrsasign 10.9.0 into your web page
* <script src="https://cdnjs.cloudflare.com/ajax/libs/jsrsasign/11.1.0/jsrsasign-all-min.js"></script>
*
* 2. Update the privateKey below with contents from private-key.pem
*
* 3. Include this script into your web page
* <script src="path/to/sign-message.js"></script>
*
* 4. Remove or comment out any other references to "setSignaturePromise"
*
* 5. IMPORTANT: Before deploying to production, copy "jsrsasign-all-min.js"
* to the web server. Don't trust the CDN above to be available.
*/
var privateKey = "-----BEGIN PRIVATE KEY-----\n" +
"MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQC0z9FeMynsC8+u\n" +
"dvX+LciZxnh5uRj4C9S6tNeeAlIGCfQYk0zUcNFCoCkTknNQd/YEiawDLNbxBqut\n" +
"bMDZ1aarys1a0lYmUeVLCIqvzBkPJTSQsCopQQ9V8WuT252zzNzs68dVGNdCJd5J\n" +
"NRQykpwexmnjPPv0mvj7i8XgG379TyW6P+WWV5okeUkXJ9eJS2ouDYdR2SM9BoVW\n" +
"+FgxDu6BmXhozW5EfsnajFp7HL8kQClI0QOc79yuKl3492rH6bzFsFn2lfwWy9ic\n" +
"7cP8EpCTeFp1tFaD+vxBhPZkeTQ1HKx6hQ5zeHIB5ySJJZ7af2W8r4eTGYzbdRW2\n" +
"4DDHCPhZAgMBAAECggEATvofR3gtrY8TLe+ET3wMDS8l3HU/NMlmKA9pxvjYfw7F\n" +
"8h4VBw4oOWPfzU7A07syWJUR72kckbcKMfw42G18GbnBrRQG0UIgV3/ppBQQNg9Y\n" +
"QILSR6bFXhLPnIvm/GxVa58pOEBbdec4it2Gbvie/MpJ4hn3K8atTqKk0djwxQ+b\n" +
"QNBWtVgTkyIqMpUTFDi5ECiVXaGWZ5AOVK2TzlLRNQ5Y7US8lmGxVWzt0GONjXSE\n" +
"iO/eBk8A7wI3zknMx5o1uZa/hFCPQH33uKeuqU5rmphi3zS0BY7iGY9EoKu/o+BO\n" +
"HPwLQJ3wCDA3O9APZ3gmmbHFPMFPr/mVGeAeGP/BAQKBgQDaPELRriUaanWrZpgT\n" +
"VnKKrRSqPED3anAVgmDfzTQwuR/3oD506F3AMBzloAo3y9BXmDfe8qLn6kgdZQKy\n" +
"SFNLz888at96oi+2mEKPpvssqiwE6F3OtEM6yv4DP9KJHaHmXaWv+/sjwjzpFNjs\n" +
"wGThBxFvrTWRJqBYsM1XNJJ2EQKBgQDUGbTSwHKqRCYWhQ1GPCZKE98l5UtMKvUb\n" +
"hyWWOXoyoeYbJEMfG1ynX4JeXIkl6YtBjYCqszv9PjHa1rowTZaAPJ0V70zyhTcF\n" +
"t581ii9LpiejIGrELHvJnW87QmjjStkjwGIqgKLp7Qe6CDjHI9HP1NM0uav/IQLW\n" +
"pB6wyEz1yQKBgQCuxPut+Ax2rzM05KB9PAnWzO1zt3U/rtm8IAF8uVVGf7r+EDJ0\n" +
"ZXJO6zj5G8WTEYHz5E86GI4ltBW0lKQoKouqdu27sMrv5trXG/CSImOcTVubQot9\n" +
"chc1CkOKTp5IeJajafO6j817wZ4N+0gNsbYYEBUCnm/7ojdfT5ficpOoQQKBgQDB\n" +
"PgKPmaNfGeQR1Ht5qEfCakR/RF/ML79Nq15FdmytQPBjfjBhYQ6Tt+MRkgGqtxOX\n" +
"UBMQc2iOnGHT3puYcrhScec1GufidhjhbqDxqMrag7HNYDWmMlk+IeA7/4+Mtp8L\n" +
"gbZuvvCvbLQDfIYueaYpUuBzQ08/jZYGdVU4/+WOcQKBgAGUN0kIB6EM1K/iZ0TN\n" +
"jlt8P5UEV3ZCyATWFiGZRhhE2WAh8gv1jx4J26pcUs1n8sd2a1h6ZuBSqsyIlNSp\n" +
"xtKsm3bqQFDHRrPcsBX4nanrw9DzkpH1k/I3WMSdGqkDAR3DtL7yXTJXJo2Sbrp5\n" +
"EjzSn7DcDE1tL2En/tSVXeUY\n" +
"-----END PRIVATE KEY-----";
qz.security.setSignatureAlgorithm("SHA512"); // Since 2.1
qz.security.setSignaturePromise(function(toSign) {
return function(resolve, reject) {
try {
var pk = KEYUTIL.getKey(privateKey);
var sig = new KJUR.crypto.Signature({"alg": "SHA512withRSA"}); // Use "SHA1withRSA" for QZ Tray 2.0 and older
sig.init(pk);
sig.updateString(toSign);
var hex = sig.sign();
console.log("DEBUG: \n\n" + stob64(hextorstr(hex)));
resolve(stob64(hextorstr(hex)));
} catch (err) {
console.error(err);
reject(err);
}
};
});

View File

@@ -0,0 +1,48 @@
//
// J# Signing Example
// Echoes the signed message and exits
//
// #########################################################
// # 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 #
// # #
// #########################################################
module sample
open System
open System.Security.Cryptography
open System.Security.Cryptography.X509Certificates
open System.IO
open System.Text
let request = "test data"
// How to associate a private key with the X509Certificate2 class in .net
// openssl pkcs12 -export -in private-key.pem -inkey digital-certificate.txt -out private-key.pfx
let cert = new X509Certificate2("private-key.pfx")
let sha1 = new SHA512CryptoServiceProvider() // Use "SHA1CryptoServiceProvider" for QZ Tray 2.0 and older
let csp = cert.PrivateKey :?> RSACryptoServiceProvider
let encoder = new ASCIIEncoding()
let data = encoder.GetBytes(request)
let binaryData = csp.SignData(data, sha1)
let output = Convert.ToBase64String(binaryData)
Console.WriteLine output

View File

@@ -0,0 +1,120 @@
<%
/*
* JSP signing example
* Echoes the signed message and exits
*/
// #########################################################
// # 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 #
// # #
// #########################################################
%>
<%@ page import="java.io.*" %>
<%@ page import="java.util.*" %>
<%@ page import="java.lang.*" %>
<%@ page import="java.security.*" %>
<%@ page import="java.security.spec.*" %>
<%@ page import="java.util.logging.*" %>
<%@ page import="javax.xml.bind.DatatypeConverter" %>
<%@ page trimDirectiveWhitespaces="true" %>
<%@ page language="java" contentType="text/plain charset=UTF-8" pageEncoding="UTF-8"%>
<%= getSignature(request.getParameter("request")) %>
<%!
/**
* Creates a signature using the provided private key and the provided (String) data inside Object o.
*/
private String getSignature(Object o) {
// Private key path if placed in CATALINA_HOME/private/ **AND** if JSP is
// placed in CATALINA_HOME/webapps/examples/. Adjust as needed.
String keyPath = "../../private/private-key.pem";
// Prepend servlet context path
keyPath = getServletContext().getRealPath("/") + keyPath;
String req = o == null ? "" : (String)o;
try {
byte[] keyData = cleanseKeyData(readData(keyPath));
// Warning: PKCS#8 required. If PKCS#1 (RSA) key is provided convert using:
// $ openssl pkcs8 -topk8 -inform PEM -outform PEM -in private-key.pem -out private-key-pkcs8.pem -nocrypt
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyData);
KeyFactory kf = KeyFactory.getInstance("RSA");
PrivateKey key = kf.generatePrivate(keySpec);
Signature sig = Signature.getInstance("SHA512withRSA"); // Use "SHA1withRSA" for QZ Tray 2.0 and older
sig.initSign(key);
sig.update(req.getBytes());
String output = DatatypeConverter.printBase64Binary(sig.sign());
return output;
} catch (Throwable t) {
t.printStackTrace();
return "Something went wrong while signing the message.\n" +
"Please check server console for sign-message.jsp";
}
}
%>
<%!
/**
* Reads the raw byte[] data from a file resource
* @param resourcePath
* @return the raw byte data from a resource file
* @throws IOException
*/
public byte[] readData(String resourcePath) throws IOException {
FileInputStream is = new FileInputStream(resourcePath);
//InputStream is = getServletContext().getResourceAsStream(resourcePath);
if (is == null) {
throw new IOException(String.format("Can't open resource \"%s\"", resourcePath));
}
DataInputStream dis = new DataInputStream(is);
byte[] data = new byte[dis.available()];
dis.readFully(data);
dis.close();
return data;
}
%>
<%!
/**
* Parses an X509 PEM formatted base64 encoded private key, returns the decoded
* private key byte data
* @param keyData PEM file contents, a X509 base64 encoded private key
* @return Private key data
* @throws IOException
*/
private byte[] cleanseKeyData(byte[] keyData) throws IOException {
StringBuilder sb = new StringBuilder();
String[] lines = new String(keyData).split("\n");
String[] skips = new String[]{"-----BEGIN", "-----END", ": "};
for (String line : lines) {
boolean skipLine = false;
for (String skip : skips) {
if (line.contains(skip)) {
skipLine = true;
}
}
if (!skipLine) {
sb.append(line.trim());
}
}
return DatatypeConverter.parseBase64Binary(sb.toString());
}
%>

View File

@@ -0,0 +1,43 @@
/*
* Node.js signing example
* Echoes the signed message and exits
*/
// #########################################################
// # 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 #
// # #
// #########################################################
var key = "private-key.pem";
//var pass = "S3cur3P@ssw0rd";
app.get('/sign', function(req, res) {
var crypto = require('crypto');
var fs = require('fs');
var path = require('path');
var toSign = req.query.requestToSign;
fs.readFile(path.join(__dirname, '\\' + key), 'utf-8', function(err, privateKey) {
var sign = crypto.createSign('SHA512'); // Use "SHA1" for QZ Tray 2.0 and older
sign.update(toSign);
var signature = sign.sign({ key: privateKey/*, passphrase: pass */ }, 'base64');
res.set('Content-Type', 'text/plain');
res.send(signature);
});
});

View File

@@ -0,0 +1,43 @@
#
# Python Odoo example for controller.py
# Echoes the signed message and exits
#
#########################################################
# 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 #
# #
#########################################################
from odoo import http
from odoo.http import request
from OpenSSL import crypto
import base64
class SignMessage(http.Controller):
@http.route('/sign-message/', auth='public')
def index(self, **kwargs):
mypass = None
key_file = open('path/to/private-key.pem', 'r')
key = key_file.read()
key_file.close()
password = None
pkey = crypto.load_privatekey(crypto.FILETYPE_PEM, key, password)
sign = crypto.sign(pkey, kwargs.get('request', ''), 'sha512') # Use 'sha1' for QZ Tray 2.0 and older
data_base64 = base64.b64encode(sign)
return request.make_response(data_base64, [('Content-Type', 'text/plain')])

View File

@@ -0,0 +1,55 @@
<?php
/*
* Echoes the signed message and exits
*/
// #########################################################
// # 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 #
// # #
// #########################################################
// Sample key. Replace with one used for CSR generation
$KEY = 'private-key.pem';
//$PASS = 'S3cur3P@ssw0rd';
$req = $_GET['request'];
$privateKey = openssl_get_privatekey(file_get_contents($KEY) /*, $PASS */);
$signature = null;
openssl_sign($req, $signature, $privateKey, "sha512"); // Use "sha1" for QZ Tray 2.0 and older
/*
// Or alternately, via phpseclib
include('Crypt/RSA.php');
$rsa = new Crypt_RSA();
$rsa.setHash('sha512'); // Use 'sha1' for QZ Tray 2.0 and older
$rsa->loadKey(file_get_contents($KEY));
$rsa->setSignatureMode(CRYPT_RSA_SIGNATURE_PKCS1);
$signature = $rsa->sign($req);
*/
if ($signature) {
header("Content-type: text/plain");
echo base64_encode($signature);
exit(0);
}
echo '<h1>Error signing message</h1>';
http_response_code(500);
exit(1);
?>

View File

@@ -0,0 +1,52 @@
#!/usr/bin/perl
#
# Echoes the signed message and exits
# usage: ./sign-message.pl "test"
#
#########################################################
# 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 #
# #
#########################################################
# RSA Crypto libs provided by:
# Debian: libcrypt-openssl-rsa-perl
# RedHat: perl-Crypt-OpenSSL-RSA
use Crypt::OpenSSL::RSA;
use MIME::Base64 qw(encode_base64);
# Get first argument passed to script
my $request = $ARGV[0];
# Path to the private key
my $pem_file = "private-key.pem";
# Read private key
my $private_key = do {
local $/ = undef;
open my $fh, "<", $pem_file
or die "could not open $file: $!";
<$fh>;
};
# Load private key
my $rsa = Crypt::OpenSSL::RSA->new_private_key($private_key);
# Create signature
$rsa->use_sha512_hash(); # use_sha1_hash for QZ Tray 2.0 and older
my $sig = encode_base64($rsa->sign($request));
print $sig;

View File

@@ -0,0 +1,39 @@
#
# Python Django example for views.py
# Echoes the signed message and exits
#
#########################################################
# 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 #
# #
#########################################################
import base64
import os
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import hashes, serialization
from cryptography.hazmat.primitives.asymmetric import padding
from django.http import HttpResponse, HttpResponseBadRequest
def get(self, request, message):
# Load signature
key = serialization.load_pem_private_key(open("private-key.pem","rb").read(), None, backend=default_backend())
# Create the signature
signature = key.sign(message.encode('utf-8'), padding.PKCS1v15(), hashes.SHA512()) # Use hashes.SHA1() for QZ Tray 2.0 and older
# Echo the signature
return HttpResponse(base64.b64encode(signature), content_type="text/plain")

View File

@@ -0,0 +1,36 @@
#!/usr/bin/env ruby
#
# Echoes the signed message and exits
# usage: ./sign-message.rb "request=test"
#
#########################################################
# 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 #
# #
#########################################################
# Typical rails controller
class PrintingController < ActionController::Base
def sign
digest = OpenSSL::Digest.new('sha512') # Use 'sha1' for QZ Tray 2.0 and older
pkey = OpenSSL::PKey::read(File.read(Rails.root.join('lib', 'certs', 'private-key.pem')))
signed = pkey.sign(digest, params[:request])
encoded = Base64.encode64(signed)
render text: encoded
end
end

View File

@@ -0,0 +1,86 @@
/*
* AngularJS example using jsrsasign (client) or fetch (server)
*/
// #########################################################
// # 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 #
// # #
// #########################################################
import { Component } from '@angular/core';
import * as qz from 'qz-tray';
import { KJUR, KEYUTIL, stob64, hextorstr } from 'jsrsasign';
qz.security.setCertificatePromise((resolve, reject) => {
fetch("assets/digital-certificate.txt", {cache: 'no-store', headers: {'Content-Type': 'text/plain'}})
.then(data => resolve(data.text()));
});
/*
* Client-side using jsrsasign
*/
qz.security.setSignatureAlgorithm("SHA512"); // Since 2.1
qz.security.setSignaturePromise(hash => {
return (resolve, reject) => {
fetch("assets/private-key.pem", {cache: 'no-store', headers: {'Content-Type': 'text/plain'}})
.then(wrapped => wrapped.text())
.then(data => {
var pk = KEYUTIL.getKey(data);
var sig = new KJUR.crypto.Signature({"alg": "SHA512withRSA"}); // Use "SHA1withRSA" for QZ Tray 2.0 and older
sig.init(pk);
sig.updateString(hash);
var hex = sig.sign();
console.log("DEBUG: \n\n" + stob64(hextorstr(hex)));
resolve(stob64(hextorstr(hex)));
})
.catch(err => console.error(err));
};
});
/*
* Preferred, from a secure controller
*
qz.security.setSignaturePromise(hash => {
return (resolve, reject) => {
fetch("/path/to/controller?request=" + hash, {cache: 'no-store', headers: {'Content-Type': 'text/plain'}})
.then(wrapped => wrapped.text())
.then(data => resolve(data))
.catch(err => console.error(err));
});
};
});
*/
qz.api.setSha256Type(data => sha256(data));
qz.api.setPromiseType(resolver => new Promise(resolver));
qz.websocket.connect()
.then(qz.printers.getDefault)
.then(printer => console.log("The default printer is: " + printer))
.then(qz.websocket.disconnect)
.catch(err => console.error(err));
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
title = 'QZ Tray AngularJS Signing';
}

View File

@@ -0,0 +1,43 @@
'
' Echoes the signed message and exits
'
Public Sub SignMessage(message As String)
'**********************************************************
'* WARNING WARNING WARNING *
'**********************************************************
'* *
'* This file is intended for demonstration purposes only. *
'* 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 *
'* *
'**********************************************************
' Sample key. Replace with one used for CSR generation
' How to associate a private key with the X509Certificate2 class in .net
' openssl pkcs12 -export -inkey private-key.pem -in digital-certificate.txt -out private-key.pfx
Dim KEY = "private-key.pfx"
Dim cert = New X509Certificate2(KEY, X509KeyStorageFlags.MachineKeySet Or X509KeyStorageFlags.PersistKeySet Or X509KeyStorageFlags.Exportable)
Dim csp As RSACryptoServiceProvider = CType(cert.PrivateKey,RSACryptoServiceProvider)
Dim cspStrong as RSACryptoServiceProvider() = New RSACryptoServiceProvider() ' 2.1 and higher: Make RSACryptoServiceProvider that can handle SHA256, SHA512
cspStrong.ImportParameters(csp.ExportParameters(true)) ' Copy to stronger RSACryptoServiceProvider
Dim data As Byte() = New ASCIIEncoding().GetBytes(message)
Dim hash As Byte() = New SHA512Managed().ComputeHash(data) ' Use SHA1Managed() for QZ Tray 2.0 and older
Response.ContentType = "text/plain"
Response.Write(Convert.ToBase64String(cspStrong.SignHash(hash, CryptoConfig.MapNameToOID("SHA512")))) ' Use "SHA1" for QZ Tray 2.0 and older
Environment.[Exit](0)
End Sub

View File

@@ -0,0 +1,88 @@
/*
* JavaScript client-side example using jwa
*/
// #########################################################
// # 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 #
// # #
// #########################################################
import Vue from "vue";
import qz from "qz-tray";
import jwa from "jwa";
const vue = new Vue({
el: "#app",
data: {
message: "QZ Tray Vue.js Demo"
},
template: "<div>{{ message }}</div>"
}).$mount();
const rsa512 = jwa("RS512");
const privateKey = getPrivateKey();
qz.security.setSignatureAlgorithm("SHA512"); // Since 2.1
qz.security.setSignaturePromise(function (toSign) {
return function (resolve, reject) {
try {
const hexUrl = rsa512.sign(toSign, privateKey);
// Crude base64URL to base64 conversion
const hex = hexUrl.replace(/_/g, "/").replace(/-/g, "+");
resolve(hex);
} catch (err) {
reject(err);
}
};
});
const certificate = getCertificate();
qz.security.setCertificatePromise((resolve, reject) => {
resolve(certificate);
});
function getPrivateKey() {
// TODO: Switch to fetch()/AJAX/etc
return (
"-----BEGIN PRIVATE KEY-----\n" +
"..." +
"-----END PRIVATE KEY-----"
);
}
function getCertificate() {
// TODO: Switch to fetch()/AJAX/etc
return (
"-----BEGIN CERTIFICATE-----\n" +
"..." +
"-----END CERTIFICATE-----"
);
}
qz.websocket
.connect()
.then(() => {
vue.message = "Looking for printers...";
return qz.printers.find();
})
.then((printers) => {
vue.message = "Found printers: " + printers;
})
.catch((err) => {
vue.message = err;
});

View File

@@ -0,0 +1,50 @@
%%%-------------------------------------------------------------------
%%% #########################################################
%%% # 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 #
%%% # #
%%% #########################################################
%%%-------------------------------------------------------------------
-module(sign_message).
-export([sign/2]).
%%%
%%% Usage:
%%% -import(sign_message, [sign/2]).
%%% [...]
%%% sign_message:sign(GetRequest, "path/to/private-key.rsa").
%%% * Where GetRequest is the the "foo" portion of "?request=foo"
%%% * Web framework must echo the base64 encoded signature in plain text
%%% * Browser must use ajax technique to fetch base64 signature
%%% * See also qz.api.setSignaturePromise(...)
%%%
%%% Important:
%%% * Private key MUST be converted to newer RSA format using the following command:
%%% openssl rsa -in "private-key.pem" -out "private-key.rsa"
%%%
%%% Watch for:
%%% badmatch,{error,enoent} key cannot be read; check for valid path
%%% function_clause,[{public_key,sign,...}] key must be converted to newer RSA format
%%%
%%%
sign(Message, KeyPath) ->
{ok, Data} = file:read_file(KeyPath),
[KeyEntry] = public_key:pem_decode(Data),
PrivateKey = public_key:pem_entry_decode(KeyEntry),
Signature = public_key:sign(list_to_binary(Message), sha512, PrivateKey), % Use sha1 for QZ Tray 2.0 and older
Base64 = base64:encode(Signature),
io:fwrite(Base64).

View File

@@ -0,0 +1,51 @@
^XA^CF,0,0,0
^FX Please avoid using PR (print rate) or MD (media darkness) commands;
They may change or be outside the range of current printer settings for subsequent print jobs and result in bad prints -lite1979^FS
^PW812^PON^CI13
^FO0,147^GB800,4,4^FS
^FO0,401^GB800,4,4^FS
^FO0,736^GB800,4,4^FS
^FO35,12^AdN,0,0^FWN^FH^FDFrom:^FS
^FO35,31^AdN,0,0^FWN^FH^FDAlex^FS
^FO35,51^AdN,0,0^FWN^FH^FDFlagship^FS
^FO35,71^AdN,0,0^FWN^FH^FD79 Spike St.^FS
^FO35,92^AdN,0,0^FWN^FH^FD^FS
^FO35,112^AdN,0,0^FWN^FH^FDNorcross, GA 30071^FS
^FO35,132^AdN,0,0^FWN^FH^FD(123) 456-7890^FS
^FO490,31^AdN,0,0^FWN^FH^FDShip Date: 31DEC07^FS
^FO490,51^AdN,0,0^FWN^FH^FDActWgt: 10.5 LB^FS
^FO490,72^AdN,0,0^FWN^FH^FDSystem#: 1195167/WSXI0100^FS
^FO490,91^AdN,0,0^FWN^FH^FDAccount: S *********^FS
^FO43,158^A0N,25,27^FWN^FH^FDSteve Jobs^FS
^FO615,156^AdN,0,0^FWN^FH^FD(123) 456-7890^FS
^FO43,193^A0N,25,27^FWN^FH^FDApple Inc.^FS
^FO43,228^A0N,25,27^FWN^FH^FD1 Infinite Loop.^FS
^FO43,263^A0N,25,27^FWN^FH^FD^FS
^FO43,296^A0N,30,30^FWN^FH^FDCupertino, CA 95014^FS
^FO530,296^A0N,35,45^FWN^FH^FD(US)^FS
^FO725,216^AdN,0,0^FWN^FH^FDGround^FS
^FO670,238^GB105,10,10^FS
^FO670,248^GB10,112,10^FS
^FO765,248^GB10,112,10^FS
^FO670,360^GB105,10,10^FS
^FO650,173^A0N,50,55^FWN^FH^FDFedEx^FS
^FO690,256^A0N,130,130^FWN^FH^FDG^FS
^FO476,3^GB4,145,4^FS
^FO10,358^A0N,15,15^FWN^FH^FDRef:^FS
^FO406,388^A0N,15,15^FWN^FH^FDDept: Work^FS
^FO10,373^A0N,15,15^FWN^FH^FDInv:^FS
^FO10,388^A0N,15,15^FWN^FH^FDPO:^FS
^FO625,495^A0N,20,35^FWN^FH^FD1^FS
^FO640,535^A0N,20,35^FWN^FH^FDof^FS
^FO625,575^A0N,20,35^FWN^FH^FD1^FS
^FO80,771^BY4,2^BCN,290,N,N,N,N^FWN^FD>;>89612019333075610004019^FS
^FO135,1083^A0N,25,27^FWN^FH^FD(9612019) 3330756 10004019^FS
^FO783,288^A0N,15,15^FWB^FH^FDCLS090607/23/23^FS
^FO10,162^A0N,20,18^FWN^FH^FDTO^FS
^FO25,1108^A0N,50,55^FWN^FH^FDGND^FS
^FO25,1150^A0N,35,45^FWN^FH^FDPrepaid^FS
^FO300,1115^A0N,35,45^FWN^FH^FD^FS
^FO300,1149^A0N,35,45^FWN^FH^FD^FS
^FO30,428^BY2,2^B7N,10,5,12^FH^FWN^FH^FD[)>_1E01_1D02950142083_1D840_1D019_1D333075610004019_1DFDEB_1D3330756_1D365_1D _1D1/1_1D10.5LB_1DN_1D1 Infinite Loop._1DCupertino_1DCA_1DSteve Jobs_1E06_1D10ZGD004_1D11ZApple Inc._1D12Z1234567890_1D23ZN_1D22Z _1CN_1D20Z _1C0_1D29Z_1D28Z_1D26Z3632_1C_1D_1E_04^FS
^PQ1
^XZ

View File

@@ -0,0 +1,228 @@
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"/>
<soapenv:Body>
<v7:ProcessShipmentReply xmlns:v7="http://fedex.com/ws/ship/v7" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<v7:HighestSeverity xmlns:java="java:com.fedex.nxgen.ship.v6.ientities">NOTE</v7:HighestSeverity>
<v7:Notifications xmlns:java="java:com.fedex.nxgen.ship.v6.ientities">
<v7:Severity>NOTE</v7:Severity>
<v7:Source>ship</v7:Source>
<v7:Code>6028</v7:Code>
<v7:Message>LabelPrintingOrientationType not specified - using default value of N</v7:Message>
<v7:LocalizedMessage>LabelPrintingOrientationType not specified - using default value of N</v7:LocalizedMessage>
</v7:Notifications>
<q0:TransactionDetail xmlns:q0="http://fedex.com/ws/ship/v7" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<q0:CustomerTransactionId>Ship Service V7</q0:CustomerTransactionId>
</q0:TransactionDetail>
<q0:Version xmlns:q0="http://fedex.com/ws/ship/v7" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<q0:ServiceId>ship</q0:ServiceId>
<q0:Major>7</q0:Major>
<q0:Intermediate>0</q0:Intermediate>
<q0:Minor>0</q0:Minor>
</q0:Version>
<v7:CompletedShipmentDetail xmlns:java="java:com.fedex.nxgen.ship.v6.ientities">
<v7:UsDomestic>true</v7:UsDomestic>
<v7:CarrierCode>FDXG</v7:CarrierCode>
<v7:ServiceTypeDescription>GROUND</v7:ServiceTypeDescription>
<v7:PackagingDescription>YOUR_PACKAGING</v7:PackagingDescription>
<v7:RoutingDetail>
<v7:TransitTime>TWO_DAYS</v7:TransitTime>
</v7:RoutingDetail>
<v7:GroundServiceCode>019</v7:GroundServiceCode>
<v7:ShipmentRating>
<v7:ActualRateType>PAYOR_ACCOUNT</v7:ActualRateType>
<v7:ShipmentRateDetails>
<v7:RateType>PAYOR_ACCOUNT</v7:RateType>
<v7:RateZone>4</v7:RateZone>
<v7:RatedWeightMethod>ACTUAL</v7:RatedWeightMethod>
<v7:DimDivisor>0</v7:DimDivisor>
<v7:FuelSurchargePercent>5.25</v7:FuelSurchargePercent>
<v7:TotalBillingWeight>
<v7:Units>LB</v7:Units>
<v7:Value>36.0</v7:Value>
</v7:TotalBillingWeight>
<v7:TotalBaseCharge>
<v7:Currency>USD</v7:Currency>
<v7:Amount>13.74</v7:Amount>
</v7:TotalBaseCharge>
<v7:TotalFreightDiscounts>
<v7:Currency>USD</v7:Currency>
<v7:Amount>7.0</v7:Amount>
</v7:TotalFreightDiscounts>
<v7:TotalNetFreight>
<v7:Currency>USD</v7:Currency>
<v7:Amount>6.74</v7:Amount>
</v7:TotalNetFreight>
<v7:TotalSurcharges>
<v7:Currency>USD</v7:Currency>
<v7:Amount>0.35</v7:Amount>
</v7:TotalSurcharges>
<v7:TotalNetFedExCharge>
<v7:Currency>USD</v7:Currency>
<v7:Amount>7.09</v7:Amount>
</v7:TotalNetFedExCharge>
<v7:TotalTaxes>
<v7:Currency>USD</v7:Currency>
<v7:Amount>0.0</v7:Amount>
</v7:TotalTaxes>
<v7:TotalNetCharge>
<v7:Currency>USD</v7:Currency>
<v7:Amount>7.09</v7:Amount>
</v7:TotalNetCharge>
<v7:TotalRebates>
<v7:Currency>USD</v7:Currency>
<v7:Amount>0.0</v7:Amount>
</v7:TotalRebates>
<v7:FreightDiscounts>
<v7:RateDiscountType>VOLUME</v7:RateDiscountType>
<v7:Description>Base</v7:Description>
<v7:Amount>
<v7:Currency>USD</v7:Currency>
<v7:Amount>4.38</v7:Amount>
</v7:Amount>
<v7:Percent>0.0</v7:Percent>
</v7:FreightDiscounts>
<v7:FreightDiscounts>
<v7:RateDiscountType>VOLUME</v7:RateDiscountType>
<v7:Description>Matrix</v7:Description>
<v7:Amount>
<v7:Currency>USD</v7:Currency>
<v7:Amount>2.62</v7:Amount>
</v7:Amount>
<v7:Percent>0.0</v7:Percent>
</v7:FreightDiscounts>
<v7:Surcharges>
<v7:SurchargeType>INSURED_VALUE</v7:SurchargeType>
<v7:Level>PACKAGE</v7:Level>
<v7:Description>Insured value</v7:Description>
<v7:Amount>
<v7:Currency>USD</v7:Currency>
<v7:Amount>0.0</v7:Amount>
</v7:Amount>
</v7:Surcharges>
<v7:Surcharges>
<v7:SurchargeType>FUEL</v7:SurchargeType>
<v7:Level>PACKAGE</v7:Level>
<v7:Description>FedEx Ground Fuel</v7:Description>
<v7:Amount>
<v7:Currency>USD</v7:Currency>
<v7:Amount>0.35</v7:Amount>
</v7:Amount>
</v7:Surcharges>
</v7:ShipmentRateDetails>
</v7:ShipmentRating>
<v7:IneligibleForMoneyBackGuarantee>false</v7:IneligibleForMoneyBackGuarantee>
<v7:CompletedPackageDetails>
<v7:SequenceNumber>1</v7:SequenceNumber>
<v7:TrackingIds>
<v7:TrackingIdType>GROUND</v7:TrackingIdType>
<v7:TrackingNumber>422268010001723</v7:TrackingNumber>
</v7:TrackingIds>
<v7:GroupNumber>0</v7:GroupNumber>
<v7:PackageRating>
<v7:ActualRateType>PAYOR_ACCOUNT</v7:ActualRateType>
<v7:PackageRateDetails>
<v7:RateType>PAYOR_ACCOUNT</v7:RateType>
<v7:RatedWeightMethod>ACTUAL</v7:RatedWeightMethod>
<v7:BillingWeight>
<v7:Units>LB</v7:Units>
<v7:Value>36.0</v7:Value>
</v7:BillingWeight>
<v7:BaseCharge>
<v7:Currency>USD</v7:Currency>
<v7:Amount>13.74</v7:Amount>
</v7:BaseCharge>
<v7:TotalFreightDiscounts>
<v7:Currency>USD</v7:Currency>
<v7:Amount>7.0</v7:Amount>
</v7:TotalFreightDiscounts>
<v7:NetFreight>
<v7:Currency>USD</v7:Currency>
<v7:Amount>6.74</v7:Amount>
</v7:NetFreight>
<v7:TotalSurcharges>
<v7:Currency>USD</v7:Currency>
<v7:Amount>0.35</v7:Amount>
</v7:TotalSurcharges>
<v7:NetFedExCharge>
<v7:Currency>USD</v7:Currency>
<v7:Amount>7.09</v7:Amount>
</v7:NetFedExCharge>
<v7:TotalTaxes>
<v7:Currency>USD</v7:Currency>
<v7:Amount>0.0</v7:Amount>
</v7:TotalTaxes>
<v7:NetCharge>
<v7:Currency>USD</v7:Currency>
<v7:Amount>7.09</v7:Amount>
</v7:NetCharge>
<v7:TotalRebates>
<v7:Currency>USD</v7:Currency>
<v7:Amount>0.0</v7:Amount>
</v7:TotalRebates>
<v7:FreightDiscounts>
<v7:RateDiscountType>VOLUME</v7:RateDiscountType>
<v7:Description>Base</v7:Description>
<v7:Amount>
<v7:Currency>USD</v7:Currency>
<v7:Amount>4.38</v7:Amount>
</v7:Amount>
<v7:Percent>0.0</v7:Percent>
</v7:FreightDiscounts>
<v7:FreightDiscounts>
<v7:RateDiscountType>VOLUME</v7:RateDiscountType>
<v7:Description>Matrix</v7:Description>
<v7:Amount>
<v7:Currency>USD</v7:Currency>
<v7:Amount>2.62</v7:Amount>
</v7:Amount>
<v7:Percent>0.0</v7:Percent>
</v7:FreightDiscounts>
<v7:Surcharges>
<v7:SurchargeType>INSURED_VALUE</v7:SurchargeType>
<v7:Level>PACKAGE</v7:Level>
<v7:Description>Insured value</v7:Description>
<v7:Amount>
<v7:Currency>USD</v7:Currency>
<v7:Amount>0.0</v7:Amount>
</v7:Amount>
</v7:Surcharges>
<v7:Surcharges>
<v7:SurchargeType>FUEL</v7:SurchargeType>
<v7:Level>PACKAGE</v7:Level>
<v7:Description>FedEx Ground Fuel</v7:Description>
<v7:Amount>
<v7:Currency>USD</v7:Currency>
<v7:Amount>0.35</v7:Amount>
</v7:Amount>
</v7:Surcharges>
</v7:PackageRateDetails>
</v7:PackageRating>
<v7:Barcodes>
<v7:BinaryBarcodes>
<v7:Type>COMMON_2D</v7:Type>
<v7:Value>Wyk+HjAxHTAyMzgwMTcdODQwHTAxOR0wMDAwMDAwMDAwMDAwMDAdRkRFQh0wMDAwMDAwHTMzNR0dMS8xHTM2LjBMQh1OHVJlY2lwaWVudCBBZGRyZXNzIExpbmUgMR1Db2xsaWVydmlsbGUdVE4dUmVjaXBpZW50IENvbnRhY3QeMDYdMTBaR0QwMDQdMTJaMTIzNDU2Nzg5MB0xNFoqKlRFU1QgTEFCRUwgLSBETyBOT1QgU0hJUCoqHTIzWk4dMjJaHE4dMjBaIBw4MB0yNlo1MzEwHB0eBA==</v7:Value>
</v7:BinaryBarcodes>
<v7:StringBarcodes>
<v7:Type>GROUND</v7:Type>
<v7:Value>9612019000000000000000</v7:Value>
</v7:StringBarcodes>
</v7:Barcodes>
<v7:Label>
<v7:Type>OUTBOUND_LABEL</v7:Type>
<v7:CopiesToPrint>1</v7:CopiesToPrint>
<v7:Parts>
<v7:DocumentPartSequenceNumber>1</v7:DocumentPartSequenceNumber>
<v7:Image>XlhBXkNGLDAsMCwwXlBSMTJeTUQzMF5QVzgwMF5QT0leQ0kxM15MSDAsMjAKXkZPMCwxNDdeR0I4MDAsNCw0XkZTCl5GTzAsNDAxXkdCODAwLDQsNF5GUwpeRk8wLDczNl5HQjgwMCw0LDReRlMKXkZPMzUsMTJeQWROLDAsMF5GV05eRkheRkRGcm9tOl5GUwpeRk8zNSwzMV5BZE4sMCwwXkZXTl5GSF5GRF5GUwpeRk8zNSw1MV5BZE4sMCwwXkZXTl5GSF5GRFRHS15GUwpeRk8zNSw3MV5BZE4sMCwwXkZXTl5GSF5GRFNOMjAwMCBUZXN0IE1ldGVyIDheRlMKXkZPMzUsOTJeQWROLDAsMF5GV05eRkheRkQxMCBGZWRleCBQYXJrd2F5XkZTCl5GTzM1LDEzMl5BZE4sMCwwXkZXTl5GSF5GRCgxMjMpIDQ1Ni03ODkwXkZTCl5GTzQ5MCw3Ml5BZE4sMCwwXkZXTl5GSF5GRENBRDogMTE4NTAwOTA3L1dTWEkyMzUwXkZTCl5GTzQzLDE5M15BME4sMjUsMjdeRldOXkZIXkZEXkZTCl5GTzQzLDIyOF5BME4sMjUsMjdeRldOXkZIXkZEUmVjaXBpZW50IEFkZHJlc3MgTGluZSAxXkZTCl5GTzQzLDI2M15BME4sMjUsMjdeRldOXkZIXkZEKipURVNUIExBQkVMIC0gRE8gTk9UIFNISVAqKl5GUwpeRk8zNSwxMTJeQWROLDAsMF5GV05eRkheRkRBdXN0aW4sIFRYIDczMzAxXkZTCl5GTzQ5MCwzMV5BZE4sMCwwXkZXTl5GSF5GRFNoaXAgRGF0ZTogMDFERUMwOV5GUwpeRk80OTAsNTFeQWROLDAsMF5GV05eRkheRkRBY3RXZ3Q6IDM2LjAgTEJeRlMKXkZPNDkwLDkxXkFkTiwwLDBeRldOXkZIXkZEQWNjb3VudDogUyAyOTY1NTY5NjNeRlMKXkZPNDMsMTU4XkEwTiwyNSwyN15GV05eRkheRkRSZWNpcGllbnQgQ29udGFjdF5GUwpeRk82MTUsMTU2XkFkTiwwLDBeRldOXkZIXkZEKDEyMykgNDU2LTc4OTBeRlMKXkZPNDMsMjk2XkEwTiwzMCwzMF5GV05eRkheRkRDb2xsaWVydmlsbGUsIFROIDM4MDE3XkZTCl5GTzUzMCwyOTZeQTBOLDM1LDQ1XkZXTl5GSF5GRChVUyleRlMKXkZPNzI1LDIxNl5BZE4sMCwwXkZXTl5GSF5GREdyb3VuZF5GUwpeRk82NzAsMjM4XkdCMTA1LDEwLDEwXkZTCl5GTzY3MCwyNDheR0IxMCwxMTIsMTBeRlMKXkZPNzY1LDI0OF5HQjEwLDExMiwxMF5GUwpeRk82NzAsMzYwXkdCMTA1LDEwLDEwXkZTCl5GTzQ3NiwzXkdCNCwxNDUsNF5GUwpeRk82NTAsMTczXkEwTiw1MCw1NV5GV05eRkheRkRGZWRFeF5GUwpeRk82OTAsMjU2XkEwTiwxMzAsMTMwXkZXTl5GSF5GREdeRlMKXkZPODAsNzcxXkJZNCwyXkJDTiwyOTAsTixOLE4sTl5GV05eRkQ+Oz44OTYxMjAxOTAwMDAwMDAwMDAwMDAwMF5GUwpeRk8xMzUsMTA4M15BME4sMjUsMjdeRldOXkZIXkZEKDk2MTIwMTkpIDAwMDAwMDAgIDAwMDAwMDAwXkZTCl5GTzc4MywyNTheQTBOLDE1LDE1XkZXQl5GSF5GREowOTMwMDkwNzMxMjEyM15GUwpeRk8xMCwxNjJeQTBOLDIwLDE4XkZXTl5GSF5GRFRPXkZTCl5GTzI1LDExMDheQTBOLDUwLDU1XkZXTl5GSF5GREdORF5GUwpeRk8yNSwxMTUwXkEwTiwzNSw0NV5GV05eRkheRkRQcmVwYWlkXkZTCl5GTzMwMCwxMTE1XkEwTiwzNSw0NV5GV05eRkheRkReRlMKXkZPMzAwLDExNDleQTBOLDM1LDQ1XkZXTl5GSF5GRF5GUwpeRk8zMCw0MjheQlkyLDJeQjdOLDEwLDUsMTJeRkheRldOXkZIXkZEWyk+XzFFMDFfMUQwMjM4MDE3XzFEODQwXzFEMDE5XzFEMDAwMDAwMDAwMDAwMDAwXzFERkRFQl8xRDAwMDAwMDBfMUQzMzVfMURfMUQxLzFfMUQzNi4wTEJfMUROXzFEUmVjaXBpZW50IEFkZHJlc3MgTGluZSAxXzFEQ29sbGllcnZpbGxlXzFEVE5fMURSZWNpcGllbnQgQ29udGFjdF8xRTA2XzFEMTBaR0QwMDRfMUQxMloxMjM0NTY3ODkwXzFEMTRaKipURVNUIExBQkVMIC0gRE8gTk9UIFNISVAqKl8xRDIzWk5fMUQyMlpfMUNOXzFEMjBaIF8xQzgwXzFEMjZaNTMxMF8xQ18xRF8xRV8wNF5GUwpeRk8xNiwzNTheQTBOLDE1LDE1XkZXTl5GSF5GRFJlZjogXkZTCl5GTzE2LDM3M15BME4sMTUsMTVeRldOXkZIXkZESU5WOiBeRlMKXkZPMTYsMzg4XkEwTiwxNSwxNV5GV05eRkheRkRQTzogXkZTCl5GTzQwNiwzODheQTBOLDE1LDE1XkZXTl5GSF5GRERlcHQ6IF5GUwpeRk82MjUsNDk1XkEwTiwyMCwzNV5GV05eRkheRkQxXkZTCl5GTzY0MCw1MzVeQTBOLDIwLDM1XkZXTl5GSF5GRG9mXkZTCl5GTzYyNSw1NzVeQTBOLDIwLDM1XkZXTl5GSF5GRDFeRlMKXlBRMQpeWFoK</v7:Image>
</v7:Parts>
</v7:Label>
<v7:SignatureOption>SERVICE_DEFAULT</v7:SignatureOption>
</v7:CompletedPackageDetails>
</v7:CompletedShipmentDetail>
</v7:ProcessShipmentReply>
</soapenv:Body>
</soapenv:Envelope>