/* $Id: TestFirmaSat.cpp $ * Last updated: * $Date: 2021-09-08 06:51:00 $ * $Version: 10.0.0 $ */ /******************************* LICENSE *********************************** * Copyright (C) 2021 David Ireland, DI Management Services Pty Limited. * All rights reserved. <www.di-mgt.com.au> <www.cryptosys.net> * The code in this module is licensed under the terms of the MIT license. * For a copy, see <http://opensource.org/licenses/MIT> **************************************************************************** */ #include <iostream> #include <fstream> #include <clocale> #include <string> #include <cctype> #include <assert.h> #include "firmasat.hpp" #ifdef _WIN32 #define WIN32_LEAN_AND_MEAN #include <windows.h> // For ``SetConsoleOutputCP(CP_UTF8);`` #endif using std::cout; using std::endl; /* Case-insensitive string comparison */ static bool iequals(std::string &str1, std::string &str2) { return ((str1.size() == str2.size()) && std::equal(str1.begin(), str1.end(), str2.begin(), [](char & c1, char & c2){ return (c1 == c2 || std::toupper(c1) == std::toupper(c2)); })); } /* Return length of file in bytes or -1 if error */ static long long file_length(const std::string &fileName) { std::ifstream file(fileName.c_str(), std::ifstream::in | std::ifstream::binary); if (!file.is_open()) { return -1; } file.seekg(0, std::ios::end); long long len = file.tellg(); file.close(); return len; } static std::string file_read_to_string(const std::string &fileName) { std::ifstream in(fileName); std::string contents((std::istreambuf_iterator<char>(in)), std::istreambuf_iterator<char>()); return contents; } int main() { // Set up console and locale for UTF-8 characters std::setlocale(LC_ALL, "en_US.utf8"); #ifdef _WIN32 // Set console display page to UTF-8 SetConsoleOutputCP(CP_UTF8); #endif cout << "__cplusplus=" << __cplusplus << endl; cout << "INTERROGATE THE CORE diFirmaSAT2 DLL:" << endl; cout << "Gen::Version=" << firmasat::Gen::Version() << endl; cout << "Gen::ModuleName=" << firmasat::Gen::ModuleName() << endl; cout << "Gen::Platform=" << firmasat::Gen::Platform() << endl; cout << "Gen::CompileTime=" << firmasat::Gen::CompileTime() << endl; cout << "Gen::LicenceType=" << firmasat::Gen::LicenceType() << endl; cout << "Gen::Comments=" << firmasat::Gen::Comments() << endl; std::string s, fname, newname, outfile, keyfile, password, certfile; std::string s1, newpassword, xmlstring, newxmlstring; std::string digest, digest1; std::string attr, attr1; std::string elementName, attributeName, query; std::string certfiledata, keyfiledata; int n; //************* // DO THE TESTS //************* try { // Overall try to catch any errors at all. cout << endl << "FORM THE PIPESTRING FROM AN XML FILE:" << endl; fname = "cfdv33a-base.xml"; s = firmasat::Sat::MakePipeStringFromXml(fname); cout << "Sat::MakePipeStringFromXml('" << fname << "')=" << s << endl; cout << endl << "SIGN AN XML FILE:" << endl; fname = "cfdv33a-base.xml"; newname = "cfdv33a_new-signed.xml"; keyfile = "emisor.key"; password = "12345678a"; /* CAUTION: DO NOT HARD-CODE REAL PASSWORDS! */ certfile = "emisor.cer"; n = firmasat::Sat::SignXml(newname, fname, keyfile, password, certfile); cout << "Sat::SignXml('" << fname << "'-->'" << newname << "') returns " << n << " (0=>success)" << endl; // Did we make a valid XML file? n = firmasat::Sat::VerifySignature(newname); cout << "Sat::VerifySignature('" << newname << "') returns " << n << " (0=>success)" << endl; cout << endl << "VERIFY A SIGNATURE IN AN XML FILE:" << endl; cout << "1. One we know is good:" << endl; fname = "cfdv33a-signed-tfd.xml"; s = firmasat::Sat::VerifySignature(fname); cout << "Sat::VerifySignature('" << fname << "') returns " << n << " (0=>success)" << endl; cout << "2. One we just made, so it should be good:" << endl; fname = newname; s = firmasat::Sat::VerifySignature(fname); cout << "Sat::VerifySignature('" << fname << "') returns " << n << " (0=>success)" << endl; cout << endl << "FORM THE DIGEST OF THE PIPESTRING IN AN XML FILE:" << endl; fname = "cfdv33a-base.xml"; digest = firmasat::Sat::MakeDigestFromXml(fname); cout << "Sat::MakeDigestFromXml('" << fname << "')=" << digest << endl; cout << endl << "EXTRACT THE DIGEST FROM THE SIGNATURE IN AN XML FILE:" << endl; fname = "cfdv33a-signed-tfd.xml"; digest1 = firmasat::Sat::ExtractDigestFromSignature(fname); cout << "Sat::ExtractDigestFromSignature('" << fname << "')=" << digest1 << endl; /* check that the two digests match (caution: upper- vs lower-case) */ assert(iequals(digest, digest1)); cout << "\nEXPECTING ERRORS..." << endl; try { s = firmasat::Sat::MakeDigestFromXml("missing.file"); cout << "MakeDigestFromXml=[" << s << "]" << endl; } catch (std::exception& e) { cout << e.what() << endl; } try { s = firmasat::Sat::MakeDigestFromXml("emisor.key"); // Not an XML file cout << "MakeDigestFromXml=[" << s << "]" << endl; } catch (std::exception& e) { cout << e.what() << endl; } // Test default Error Message after a successful method call... n = firmasat::Gen::Version(); cout << "Default ErrorMessage=[" << firmasat::Err::FormatErrorMessage() << "]" << endl; cout << "...END ERRORS" << endl << endl; cout << endl << "VALIDATE THE STRUCTURE OF XML FILES:" << endl; cout << "1. A valid one:" << endl; fname = "cfdv33a-signed-tfd.xml"; n = firmasat::Sat::ValidateXml(fname); cout << "Sat::ValidateXml('" << fname << "') returns " << n << " (0=>success)" << endl; cout << "2. An invalid one (missing version):" << endl; fname = "cfdv33a-bad-nover.xml"; n = firmasat::Sat::ValidateXml(fname); cout << "Sat::ValidateXml('" << fname << "') returns " << n << " (0=>success)" << endl; cout << "Err::LastError=[" << firmasat::Err::LastError() << "]" << endl; cout << "3. Not complying with SAT spec:" << endl; fname = "cfdv33a-badspec.xml"; n = firmasat::Sat::ValidateXml(fname); cout << "Sat::ValidateXml('" << fname << "') returns " << n << " (0=>success)" << endl; cout << "Err::LastError=[" << firmasat::Err::LastError() << "]" << endl; cout << "4. Valid XML but invalid type:" << endl; fname = "V3_2_BadCurp.xml"; n = firmasat::Sat::ValidateXml(fname); cout << "Sat::ValidateXml('" << fname << "') returns " << n << " (0=>success)" << endl; cout << "Err::LastError=[" << firmasat::Err::LastError() << "]" << endl; n = firmasat::Sat::ValidateXml(fname, firmasat::Sat::XmlOption::Loose); cout << "Sat::ValidateXml('" << fname << "', Loose) returns " << n << " (0=>success)" << endl; cout << endl << "EXTRACT AN ATTRIBUTE FROM AN XML FILE:" << endl; fname = "cfdv33a-signed-tfd.xml"; elementName = "Comprobante"; attributeName = "Sello"; // NB Capital letter 'S' s = firmasat::Sat::GetXmlAttribute(fname, attributeName, elementName); cout << "Sat::GetXmlAttribute=" << s << endl; cout << "ATTRIBUTE MISSING..." << endl; attributeName = "missing"; s = firmasat::Sat::GetXmlAttribute(fname, attributeName, elementName); cout << "Sat::GetXmlAttribute=" << s << endl; if (firmasat::Sat::XmlNoMatch() == s) { cout << "Matches XmlNoMatch()" << endl; } // XmlNoMatch tests... cout << "Sat::XmlNoMatch=" << firmasat::Sat::XmlNoMatch() << endl; if (firmasat::Sat::XmlNoMatch() == s) { cout << " Match for firmasat::Sat::XmlNoMatch()" << endl; } firmasat::Sat::SetXmlNoMatch("##No coinciden##"); cout << "Sat::XmlNoMatch=" << firmasat::Sat::XmlNoMatch() << endl; s = firmasat::Sat::GetXmlAttribute(fname, attributeName, elementName); cout << "Sat::GetXmlAttribute=" << s << endl; // Set as default firmasat::Sat::SetXmlNoMatch(); cout << "Sat::XmlNoMatch(default)=" << firmasat::Sat::XmlNoMatch() << endl; cout << "EXTRACT AN ATTRIBUTE WITH ACCENTED CHARACTERS:" << endl; fname = "cfdv33a-base.xml"; elementName = "cfdi:Emisor"; attributeName = "Nombre"; s = firmasat::Sat::GetXmlAttribute(fname, attributeName, elementName); cout << "Sat::GetXmlAttribute=" << s << endl; cout << "EXTRACT AN ATTRIBUTE WITH ACCENTED CHARACTERS IN ITS NAME:" << endl; fname = "cfdv33a-nomina12.xml"; elementName = "nomina12:CompensacionSaldosAFavor"; attributeName = "Año"; // Hardcoded enye: 'A' + U+00F1 LATIN SMALL LETTER N WITH TILDE + 'o' s = firmasat::Sat::GetXmlAttribute(fname, attributeName, elementName); cout << "Sat::GetXmlAttribute=" << s << endl; cout << "EXTRACT AN ATTRIBUTE VALUE WHICH IS EMPTY:" << endl; s = firmasat::Sat::GetXmlAttribute("<a e=''></a>", "e", "a"); cout << "Sat::GetXmlAttribute='" << s << "'" << endl; cout << "\nATTEMPT TO EXTRACT AN ATTRIBUTE VALUE FROM INVALID DATA..." << endl; try { s = firmasat::Sat::GetXmlAttribute("missing.file", "e", "a"); cout << "GetXmlAttribute=[" << s << "]" << endl; } catch (std::exception& e) { cout << e.what() << endl; } try { s = firmasat::Sat::GetXmlAttribute("<a badxml>", "e", "a"); cout << "GetXmlAttribute=[" << s << "]" << endl; } catch (std::exception& e) { cout << e.what() << endl; } cout << "\nQUERY X.509 CERTIFICATE:" << endl; cout << "1. From embedded `certificado` in XML" << endl; fname = "cfdv33a-signed-tfd.xml"; cout << "FILE: " << fname << endl; query = "serialNumber"; s = firmasat::Sat::QueryCert(fname, query); cout << "Sat::QueryCert(" << query << ")=[" << s << "]" << endl; query = "rfc"; s = firmasat::Sat::QueryCert(fname, query); cout << "Sat::QueryCert(" << query << ")=[" << s << "]" << endl; query = "organizationName"; s = firmasat::Sat::QueryCert(fname, query); cout << "Sat::QueryCert(" << query << ")=[" << s << "]" << endl; cout << "2. From X.509 file" << endl; fname = "pac.cer"; cout << "FILE: " << fname << endl; query = "serialNumber"; s = firmasat::Sat::QueryCert(fname, query); cout << "Sat::QueryCert(" << query << ")=[" << s << "]" << endl; query = "rfc"; s = firmasat::Sat::QueryCert(fname, query); cout << "Sat::QueryCert(" << query << ")=[" << s << "]" << endl; query = "organizationName"; s = firmasat::Sat::QueryCert(fname, query); cout << "Sat::QueryCert(" << query << ")=[" << s << "]" << endl; cout << "\nGET CERTIFICATE AS A BASE64 STRING:" << endl; fname = "emisor.cer"; cout << "FILE: " << fname << endl; s = firmasat::Sat::GetCertAsString(fname); cout << "Sat::GetCertAsString:" << endl << s << endl; // Compare against string from XML file fname = "cfdv33a-signed-tfd.xml"; cout << "FILE: " << fname << endl; s1 = firmasat::Sat::GetCertAsString(fname); cout << "Sat::GetCertAsString:" << endl << s1 << endl; // Make sure they match assert(s == s1); cout << "\nMAKE A SIGNATURE FROM A BASE XML FILE:" << endl; fname = "cfdv33a-base.xml"; keyfile = "emisor.key"; password = "12345678a"; /* CAUTION: DO NOT HARD-CODE REAL PASSWORDS! */ s = firmasat::Sat::MakeSignatureFromXml(fname, keyfile, password); cout << "Sat::MakeSignatureFromXml:" << endl << s << endl; cout << "\nCHECK PRIVATE KEY MATCHES PUBLIC KEY IN CERTIFICATE:" << endl; certfile = "emisor.cer"; keyfile = "emisor.key"; password = "12345678a"; /* CAUTION: DO NOT HARD-CODE REAL PASSWORDS! */ n = firmasat::Sat::CheckKeyAndCert(keyfile, password, certfile); cout << "Sat::CheckKeyAndCert(" << keyfile << ", " << certfile << ") returns " << n << " (expected 0)" << endl; assert(0 == n); /* Get embedded certificate from XML doc */ certfile = "cfdv33a-signed-tfd.xml"; keyfile = "emisor.key"; n = firmasat::Sat::CheckKeyAndCert(keyfile, password, certfile); cout << "Sat::CheckKeyAndCert(" << keyfile << ", " << certfile << ") returns " << n << " (expected 0)" << endl; assert(0 == n); cout << "Expecting errors..." << endl; // Now do it wrong: note no exceptions, just a nonzero return value. certfile = "pac.cer"; n = firmasat::Sat::CheckKeyAndCert(keyfile, password, certfile); cout << "Sat::CheckKeyAndCert(" << keyfile << ", " << certfile << ") returns " << n << " (expected nonzero)" << endl; assert(0 != n); cout << " " << firmasat::Err::FormatErrorMessage(n) << endl; certfile = "emisor.cer"; keyfile = "emisor.key"; password = "badpassword"; n = firmasat::Sat::CheckKeyAndCert(keyfile, password, certfile); cout << "Sat::CheckKeyAndCert(" << keyfile << ", " << certfile << ", wrong-password) returns " << n << " (expected nonzero)" << endl; assert(0 != n); cout << " " << firmasat::Err::FormatErrorMessage(n) << endl; cout << "\nGET RECEIPT (COMPROBANTE) VERSION NUMBER FROM XML FILE:" << endl; fname = "cfdv33a-base.xml"; n = firmasat::Sat::XmlReceiptVersion(fname); cout << "Sat::XmlReceiptVersion('" << fname << "')=" << n << endl; assert(33 == n); // One-liners used in documentation cout << firmasat::Sat::XmlReceiptVersion("cfdv33a-base.xml") << endl; // 33 cout << firmasat::Sat::XmlReceiptVersion("ConVolE12345-base.xml") << endl; // 4011 cout << "\nCREATE CADENA ORIGINAL DEL TIMBRE FISCAL DIGITAL (PIPESTRING FOR TFD):" << endl; fname = "cfdv33a-signed-tfd.xml"; s = firmasat::Tfd::MakePipeStringFromXml(fname); cout << "Tfd::MakePipeStringFromXml('" << fname << "')=" << endl << s << endl; cout << "\nFORM DIGEST OF PIPESTRING FOR TFD:" << endl; fname = "cfdv33a-signed-tfd.xml"; digest = firmasat::Tfd::MakeDigestFromXml(fname); cout << "Tfd::MakeDigestFromXml('" << fname << "')=" << endl << digest << endl; cout << "\nEXTRACT DIGEST FROM TFD SELLOSAT:" << endl; fname = "cfdv33a-signed-tfd.xml"; certfile = "pac.cer"; // NB certificate is required for TFD option digest1 = firmasat::Tfd::ExtractDigestFromSignature(fname, certfile); cout << "Tfd::ExtractDigestFromSignature('" << fname << ", " << certfile << "')=" << endl << digest1 << endl; assert(iequals(digest, digest1)); cout << "\nPRETEND WE ARE A PAC WITH A KEY ALLOWED TO SIGN THE TFD:" << endl; fname = "cfdv33a-signed-tfd.xml"; keyfile = "pac.key"; password = "12345678a"; /* CAUTION: DO NOT HARD-CODE REAL PASSWORDS! */ s = firmasat::Tfd::MakeSignatureFromXml(fname, keyfile, password); cout << "Tfd::MakeSignatureFromXml('" << fname << ", " << keyfile << "')=" << endl << s << endl; cout << "\nVERIFY SIGNATURE IN TFD SELLOSAT:" << endl; fname = "cfdv33a-signed-tfd.xml"; certfile = "pac.cer"; n = firmasat::Tfd::VerifySignature(fname, certfile); cout << "Tfd::VerifySignature('" << fname << ", " << certfile << "')=" << n << " (expected 0)" << endl; assert(n == 0); cout << "\nADD A TFD ELEMENT TO A SIGNED CFDI DOCUMENT USING PAC KEY:" << endl; fname = "cfdv33a-signed.xml"; newname = "cfdv33a_new-tfd.xml"; certfile = "pac.cer"; keyfile = "pac.key"; password = "12345678a"; n = firmasat::Tfd::AddSignedTfd(newname, fname, keyfile, password, certfile); cout << "Tfd::AddSignedTfd('" << fname << "'-->'" << newname << "') returns " << n << " (expected 0)" << endl; assert(n == 0); // Did we make a valid XML file? n = firmasat::Sat::ValidateXml(newname); cout << "Sat::ValidateXml('" << newname << "') returns " << n << endl; assert(n == 0); // Does it have a valid selloSAT? n = firmasat::Tfd::VerifySignature(newname, certfile); cout << "Tfd::VerifySignature('" << newname << ", " << certfile << "')=" << n << " (expected 0)" << endl; assert(n == 0); cout << "\nADD UTF-8 BOM TO EXISTING FILE:" << endl; fname = "cfdv33a-signed-nobom.xml"; newname = "cfdv33a_new-signed-with-BOM.xml"; n = firmasat::Sat::FixBOM(newname, fname); cout << "Sat::FixBOM(" << fname << "->" << newname << ")=" << n << " (expected 0)" << endl; assert(n == 0); cout << "\nEXTRACT ATTRIBUTES FROM CONSECUTIVE ELEMENTS:" << endl; fname = "ejemplo_v32-tfd2015.xml"; attributeName = "descripcion"; elementName = "cfdi:Concepto"; cout << "For file '" << fname << "'" << endl; // Loop until NoMatch for (int i = 1; i <= 100; i++) { std::string eName = elementName + "[" + std::to_string(i) + "]"; s = firmasat::Sat::GetXmlAttribute(fname, attributeName, eName); cout << "Sat::GetXmlAttribute(" << attributeName<< "," << eName << ")=" << s << endl; if (s == firmasat::Sat::XmlNoMatch()) { break; } } cout << "\nVALIDATE XML WITH STRICT AND LOOSE OPTIONS:" << endl; cout << "Default strict behaviour (badly formed CURP attribute):" << endl; fname = "V3_2_BadCurp.xml"; n = firmasat::Sat::ValidateXml(fname); cout << "Sat::ValidateXml('" << fname << "') returns " << n << " (expected -ve error)" << endl; cout << firmasat::Err::FormatErrorMessage(n) << endl; assert(n != 0); cout << "Using XmlOption.Loose:" << endl; n = firmasat::Sat::ValidateXml(fname, firmasat::Sat::XmlOption::Loose); cout << "Sat::ValidateXml('" << fname << "', XmlOption.Loose) returns " << n << " (expected 0)" << endl; assert(n == 0); cout << "\nGET PRIVATE KEY AS BASE64:" << endl; fname = "emisor.key"; password = "12345678a"; s = firmasat::Sat::GetKeyAsString(fname, password); cout << "Sat::GetKeyAsString('" << fname<< "')=" << endl << s << endl; s = firmasat::Sat::GetKeyAsString(fname, password, firmasat::Sat::KeyOption::EncryptedPEM); cout << "Sat::GetKeyAsString('" << fname << "', EncryptedPEM)=" << endl << s << endl; cout << "\nWRITE PFX FROM PRIVATE KEY AND CERT:" << endl; newname = "archivo_new-pfx.txt"; certfile = "emisor.cer"; keyfile = "emisor.key"; password = "12345678a"; newpassword = "clavedesalida"; n = firmasat::Sat::WritePfxFile(newname, newpassword, keyfile, password, certfile); cout << "Sat::WritePfxFile() returns " << n << " (expected 0)" << endl; assert(n == 0); cout << " Created new file '" << newname << "' of length " << file_length(newname) << " bytes" << endl; cout << "\nSAVE KEYFILE WITH NEW PASSWORD..." << endl; keyfile = "emisor.key"; password = "12345678a"; newname = "emisor_new.key"; newpassword = "password123"; n = firmasat::Sat::NewKeyFile(newname, newpassword, keyfile, password); cout << "Sat::NewKeyFile() returns " << n << " (expected 0)" << endl; assert(0 == n); cout << " Created new file '" << newname << "' of length " << file_length(newname) << " bytes" << endl; // And again but saving as a PEM file instead of binary keyfile = "emisor.key"; password = "12345678a"; newname = "emisor_new.pem"; newpassword = "password123"; n = firmasat::Sat::NewKeyFile(newname, newpassword, keyfile, password, firmasat::Sat::KeyFormat::PEM); cout << "Sat::NewKeyFile() returns " << n << " (expected 0)" << endl; assert(0 == n); cout << " Created new file '" << newname << "' of length " << file_length(newname) << " bytes" << endl; cout << "\nASCIIFY AN XML DOC..." << endl; fname = "cfdv33a-base.xml"; cout << "FILE: " << fname << endl; s = firmasat::Sat::Asciify(fname); cout << s << endl; // XML with non-ascii chars in the tag or element _name_ (these cannot be asciified) fname = "cfdv33a-nomina12B.xml"; cout << "FILE: " << fname << endl; s = firmasat::Sat::Asciify(fname); cout << s << endl; cout << "\nCHECK MESSAGE DIGEST IS THE SAME FOR THE ORIGINAL FILE AND THE ASCIIFIED STRING..." << endl; digest = firmasat::Sat::MakeDigestFromXml(fname); cout << "Digest(file) =" << digest << endl; digest1 = firmasat::Sat::MakeDigestFromXml(s); cout << "Digest(string)=" << digest << endl; assert(digest == digest1); cout << "\nGENERATE 3 UUIDs:" << endl; for (int i = 0; i < 3; i++) { s = firmasat::Sat::Uuid(); cout << s << endl; } cout << "\nINSERT CERTIFICATE DETAILS INTO XML..." << endl; fname = "cfdv33a-base-nocertnum.xml"; newname = "cfdv33a-base_new-pluscert.xml"; certfile = "emisor.cer"; n = firmasat::Sat::InsertCert(newname, fname, certfile); cout << "Sat::InsertCert() returns " << n << " (expecting 0)" << endl; assert(0 == n); // Check noCertificado attribute just inserted // Original should be empty attr = firmasat::Sat::GetXmlAttribute(fname, "NoCertificado", "cfdi:Comprobante"); cout << "Old NoCertificado=[" << attr << "]" << endl; attr1 = firmasat::Sat::GetXmlAttribute(newname, "NoCertificado", "cfdi:Comprobante"); cout << "New NoCertificado=[" << attr1 << "]" << endl; cout << "\nINSERT CERTIFICATE DETAILS INTO XML AS STRING..." << endl; s = firmasat::Sat::InsertCertToString(fname, certfile); cout << "Sat::InsertCertToString() returns a string of length " << s.length() << endl; assert(s.length() > 0); attr1 = firmasat::Sat::GetXmlAttribute(s, "NoCertificado", "cfdi:Comprobante"); cout << "New NoCertificado=[" << attr1 << "]" << endl; cout << "\nSIGN XML TO STRING:" << endl; fname = "cfdv33a-base.xml"; // Read an XML file into a string xmlstring = file_read_to_string(fname); cout << "String from file '" << fname << "' has " << xmlstring.length() << " bytes" << endl; /* We can pass key file and certificate as "PEM" strings. The "BEGIN/END" encapsulation is optional for a certificate, but is required for the encrypted private key. */ certfiledata = "-----BEGIN CERTIFICATE-----" "MIIF+TCCA+GgAwIBAgIUMzAwMDEwMDAwMDAzMDAwMjM3MDgwDQYJKoZIhvcNAQELBQAwggFmMSAwHgY" "DVQQDDBdBLkMuIDIgZGUgcHJ1ZWJhcyg0MDk2KTEvMC0GA1UECgwmU2VydmljaW8gZGUgQWRtaW5pc3" "RyYWNpw7NuIFRyaWJ1dGFyaWExODA2BgNVBAsML0FkbWluaXN0cmFjacOzbiBkZSBTZWd1cmlkYWQgZ" "GUgbGEgSW5mb3JtYWNpw7NuMSkwJwYJKoZIhvcNAQkBFhphc2lzbmV0QHBydWViYXMuc2F0LmdvYi5t" "eDEmMCQGA1UECQwdQXYuIEhpZGFsZ28gNzcsIENvbC4gR3VlcnJlcm8xDjAMBgNVBBEMBTA2MzAwMQs" "wCQYDVQQGEwJNWDEZMBcGA1UECAwQRGlzdHJpdG8gRmVkZXJhbDESMBAGA1UEBwwJQ295b2Fjw6FuMR" "UwEwYDVQQtEwxTQVQ5NzA3MDFOTjMxITAfBgkqhkiG9w0BCQIMElJlc3BvbnNhYmxlOiBBQ0RNQTAeF" "w0xNzA1MTgwMzU0NTZaFw0yMTA1MTgwMzU0NTZaMIHlMSkwJwYDVQQDEyBBQ0NFTSBTRVJWSUNJT1Mg" "RU1QUkVTQVJJQUxFUyBTQzEpMCcGA1UEKRMgQUNDRU0gU0VSVklDSU9TIEVNUFJFU0FSSUFMRVMgU0M" "xKTAnBgNVBAoTIEFDQ0VNIFNFUlZJQ0lPUyBFTVBSRVNBUklBTEVTIFNDMSUwIwYDVQQtExxBQUEwMT" "AxMDFBQUEgLyBIRUdUNzYxMDAzNFMyMR4wHAYDVQQFExUgLyBIRUdUNzYxMDAzTURGUk5OMDkxGzAZB" "gNVBAsUEkNTRDAxX0FBQTAxMDEwMUFBQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJdU" "csHIEIgwivvAantGnYVIO3+7yTdD1tkKopbL+tKSjRFo1ErPdGJxP3gxT5O+ACIDQXN+HS9uMWDYnaU" "RalSIF9COFCdh/OH2Pn+UmkN4culr2DanKztVIO8idXM6c9aHn5hOo7hDxXMC3uOuGV3FS4ObkxTV+9" "NsvOAV2lMe27SHrSB0DhuLurUbZwXm+/r4dtz3b2uLgBc+Diy95PG+MIu7oNKM89aBNGcjTJw+9k+Wz" "JiPd3ZpQgIedYBD+8QWxlYCgxhnta3k9ylgXKYXCYk0k0qauvBJ1jSRVf5BjjIUbOstaQp59nkgHh45" "c9gnwJRV618NW0fMeDzuKR0CAwEAAaMdMBswDAYDVR0TAQH/BAIwADALBgNVHQ8EBAMCBsAwDQYJKoZ" "IhvcNAQELBQADggIBABKj0DCNL1lh44y+OcWFrT2icnKF7WySOVihx0oR+HPrWKBMXxo9KtrodnB1tg" "Ix8f+Xjqyphhbw+juDSeDrb99PhC4+E6JeXOkdQcJt50Kyodl9URpCVWNWjUb3F/ypa8oTcff/eMftQ" "ZT7MQ1Lqht+xm3QhVoxTIASce0jjsnBTGD2JQ4uT3oCem8bmoMXV/fk9aJ3v0+ZIL42MpY4POGUa/iT" "aawklKRAL1Xj9IdIR06RK68RS6xrGk6jwbDTEKxJpmZ3SPLtlsmPUTO1kraTPIo9FCmU/zZkWGpd8ZE" "AAFw+ZfI+bdXBfvdDwaM2iMGTQZTTEgU5KKTIvkAnHo9O45SqSJwqV9NLfPAxCo5eRR2OGibd9jhHe8" "1zUsp5GdE1mZiSqJU82H3cu6BiE+D3YbZeZnjrNSxBgKTIf8w+KNYPM4aWnuUMl0mLgtOxTUXi9MKnU" "ccq3GZLA7bx7Zn211yPRqEjSAqybUMVIOho6aqzkfc3WLZ6LnGU+hyHuZUfPwbnClb7oFFz1PlvGOpN" "DsUb0qP42QCGBiTUseGugAzqOP6EYpVPC73gFourmdBQgfayaEvi3xjNanFkPlW1XEYNrYJB4yNjphF" "rvWwTY86vL2o8gZN0Utmc5fnoBTfM9r2zVKmEi6FUeJ1iaDaVNv47te9iS1ai4V4vBY8r" "-----END CERTIFICATE-----"; keyfiledata = "-----BEGIN ENCRYPTED PRIVATE KEY-----" "MIIFDjBABgkqhkiG9w0BBQ0wMzAbBgkqhkiG9w0BBQwwDgQI5qDMtGWYa2wCAggA" "MBQGCCqGSIb3DQMHBAhFAqj+c0f8JASCBMhNUpNUp57vMu8L3LHBKRBTFl0VE3oq" "BIEKBHFYYz063iiS0Y3tPW3cplLTSqG25MdbIQcHCxwmPVYNdetHUjqjeR+TklWg" "tnMbLqvdMmmRxAFuHXznHFIa4U+YNedhFm7sdR2DsGFijm3vIpUbvpILtpTrhog/" "EHAvZXV6+F86cYc9+LUg3d0DRwJc+sWmk+2xOoXvOvvpnnQqfhQxkSknfITmc+HA" "WgHbKLK2q6e2RixjpWn0sA9LslYD0ZDn5uhrce+QEfK97asraFfiteqXf2Ll8B54" "Ku/er+O2JEu62vVDFumwMtZOuHKH4NbjOmMzKIwRTKp/1jp6OTGYSKIRiTDXnTET" "JwgItHahf7UAoM/qnkJa17Ood4hiCYopMyCXdhyMDJoFhWRanQODaiocb7XpMm1S" "EpTtHZeKgEVWSc/obYgSgs4iY497UR2MUVZQSCBdRXCgs5g1c31cCwAZ6r41KMoL" "OBVLtRXoT0mc0D6ovlwYuJhqYvuwjdNkWJS7qwXuy8b2ux4t027NGUXmgtb9XQDm" "8yJrdTtm0CktWPKe7i2tQtBC2tAjduGAlBrzY+whySRN8KUJQbYKhOBaLXgEPI93" "wi/SKHJO13WvfqqjKqrqJwB3tvhjz5E1uDKmDFoivdS76uq+k/xpmF5OWBmypWNV" "iw7kgvmH1OeTBKYkUHIL85skL6pdycGnTk3g0AmG9xtPYu6pdSqUv+N8QmTdmmdu" "85fDEN0fk2t2BRPANsbIqxopVfj5qIwm+8TbZDdNj8OssxrC5sRy5yDBjV4J+x25" "3yaILn7wgUR6Yj6GaHUUF4GISmFZ/PTbnVPDd424w6hGV8NKtUHXq5ms2kJXo6XG" "iGqjbdePM53QhdSrxTM5Dt76RcAInky6w5s/7gvT/w7tdbVA/SPhp4xgaT8Crmjb" "k3upcSqNI0HuROBxOs0gRRAWXScUZJ0Vd1V0F+C5cG2R1CtGTYeRmIAwLwcWf6Dj" "Y1Q+TOe/W3eTatOo+gIozjYDCk5ZNfeQzq4p1ApN6+gzS8kNxtvKOYJogjV74RK/" "Xl7u7oLv4SZT7Nl1YRpScW1ouIcNNTP0AC+j2OFZ3YueN8CcmvXbgSW8pYRooTxn" "Ffo9sdOL624uwRyb2DwwLO0Vo3aBIEIf8sm9sqocXmwh9sxFPEbTXPCuMSao8Qjy" "BOlsCem2589NVZs0h0ipGwdbatcjkgf+hzRoYBdlvHtKHJ8gL/A/Ap8z0+TK5NaV" "WUA+zXOZRZ66NYfs18DEbJKjwOcnnsLcfAMYoSn697148sL4JBv8IOmM6QXfxCl/" "0yU0d5/876L5jOL56lfH0eBk8s2nioAl3yRBl2wlihWi39sA0bsdHFKYEX+LqPBB" "CAdxZAvXCCJcdEdxOXSgEiFAmW9+IXFT/WJeGcZ4OmCd3Qf0fxGqFXA/9hIUumWd" "e6s0wN8LjXuFZQaMDaaVIGXKguP3OijsfBF0PYzI+L6CfUi2BLaYNJTlbQxbncmW" "2PKeDiypgt3ZY1PKV66o5OAJEAkV3vf9cRwXE5T8GwZHA+wx2rWC98hkH15xfI9q" "EsYulVdcXWzCF58HFQjUoDon0e/QMukS0eNgq9ipmoKAWKyy7+TQw7Xx3MmqkGlL" "HGM=" "-----END ENCRYPTED PRIVATE KEY-----"; password = "12345678a"; // Check key and certificate are matched n = firmasat::Sat::CheckKeyAndCert(keyfiledata, password, certfiledata); cout << "Sat::CheckKeyAndCert(STRINGS) returns " << n << " (expecting 0)" << endl; // Create a new string containing signed XML (UTF-8 encoded), all input passed in memory newxmlstring = firmasat::Sat::SignXmlToString(xmlstring, keyfiledata, password, certfiledata); cout << "Signed XML string has " << newxmlstring.length() << " bytes" << endl; cout << "\nPASS XML STRING TO OTHER SAT FUNCTIONS:" << endl; n = firmasat::Sat::ValidateXml(newxmlstring); cout << "Sat::ValidateXml(STRING) returns " << n << " (expecting 0)" << endl; assert(0 == n); n = firmasat::Sat::VerifySignature(newxmlstring); cout << "Sat::VerifySignature(STRING) returns " << n << " (expecting 0)" << endl; assert(0 == n); n = firmasat::Sat::XmlReceiptVersion(newxmlstring); cout << "Sat::XmlReceiptVersion(STRING) returns " << n << " (expecting 33)" << endl; assert(n > 0); // ****************************************** // FINALLY, DISPLAY QUICK INFO ABOUT THE CORE DLL cout << "\nFINALLY, DETAILS OF CORE NATIVE DLL..." << endl; cout << "DLL Version=" << firmasat::Gen::Version() << " [" << firmasat::Gen::Platform() << "] Lic={" << firmasat::Gen::LicenceType() << "} Compiled=[" << firmasat::Gen::CompileTime() << "] " << endl; cout << "[" << firmasat::Gen::ModuleName() << "]" << endl; cout << endl << "ALL DONE." << endl; } catch (std::exception& e) { cout << e.what() << endl; cout << "TESTS FAILED TO COMPLETE!!" << endl; } }