Compare commits

..

5 Commits

Author SHA1 Message Date
42257ca447 verify ooxml file. developing... 2017-05-12 18:59:57 +03:00
6f2fdcd971 verify ooxml file. developing... 2017-05-12 18:25:18 +03:00
9b4b7a26fd verify ooxml file. developing... 2017-05-12 18:04:13 +03:00
4d688b3922 . 2017-05-12 13:46:13 +03:00
be8d427e26 . 2017-05-12 13:17:26 +03:00
7 changed files with 351 additions and 66 deletions

View File

@ -305,6 +305,19 @@ namespace XmlUtils
strValues.push_back (NSFile::CUtf8Converter::GetUnicodeStringFromUTF8((BYTE*)p->second.c_str(), (long)p->second.length()));
}
}
template<typename T>
void ReadAllAttributesA(T& strNames, T& strValues)
{
if (!IsValid())
return;
std::map<std::string, std::string>::iterator p;
for (p = m_pBase->m_attributes.begin(); p != m_pBase->m_attributes.end(); ++p)
{
strNames.push_back(p->first);
strValues.push_back(p->second);
}
}
template <typename T>
void ReadNodeValueBase(const wchar_t* bsName, T& value)
{

View File

@ -44,7 +44,7 @@ public:
std::wstring sXml = L"<Reference URI=\"" + file + L"?ContentType=" + content_type + L"\">";
sXml += L"<DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\"/>";
sXml += L"<DigestValue>";
sXml += UTF8_TO_U(m_certificate->GetHash(m_sFolder + file));
sXml += UTF8_TO_U(m_certificate->GetHash(m_sFolder + file, OOXML_HASH_ALG_SHA1));
sXml += L"</DigestValue>";
sXml += L"</Reference>";
return sXml;
@ -54,7 +54,7 @@ public:
{
std::string sXmlSigned = U_TO_UTF8(xml);
sXmlSigned = CXmlCanonicalizator::Execute(sXmlSigned, XML_C14N_1_0);
return m_certificate->GetHash(sXmlSigned);
return m_certificate->GetHash(sXmlSigned, OOXML_HASH_ALG_SHA1);
}
std::string GetReferenceMain(const std::wstring& xml, const std::wstring& id, const bool& isCannon = true)
@ -491,7 +491,7 @@ Type=\"http://schemas.openxmlformats.org/package/2006/relationships/digital-sign
m_signed_info.WriteString("<Reference Type=\"http://uri.etsi.org/01903#SignedProperties\" URI=\"#idSignedProperties\">");
m_signed_info.WriteString("<Transforms><Transform Algorithm=\"http://www.w3.org/TR/2001/REC-xml-c14n-20010315\"/></Transforms>");
m_signed_info.WriteString("<DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\"/><DigestValue>");
m_signed_info.WriteString(m_certificate->GetHash(sXmlTmp));
m_signed_info.WriteString(m_certificate->GetHash(sXmlTmp, OOXML_HASH_ALG_SHA1));
m_signed_info.WriteString("</DigestValue></Reference>");
return (L"<Object><xd:QualifyingProperties xmlns:xd=\"http://uri.etsi.org/01903/v1.3.2#\" Target=\"#idPackageSignature\">\

View File

@ -0,0 +1,248 @@
#ifndef _XML_OOXMLVERIFIER_H_
#define _XML_OOXMLVERIFIER_H_
#include "./XmlCanonicalizator.h"
#include "./XmlTransform.h"
#include "./XmlCertificate.h"
#define OOXML_SIGNATURE_VALID 0
#define OOXML_SIGNATURE_INVALID 1
#define OOXML_SIGNATURE_NOTSUPPORTED 2
#define OOXML_SIGNATURE_BAD 3
class COOXMLSignature
{
private:
int m_valid;
std::string m_guid;
ICertificate* m_cert;
std::string m_sImageValidBase64;
std::string m_sImageInvalidBase64;
private:
XmlUtils::CXmlNode m_node; // signature file
class CXmlStackNamespaces
{
public:
std::wstring m_namespaces;
XmlUtils::CXmlNode m_node;
public:
CXmlStackNamespaces(const CXmlStackNamespaces& src)
{
m_namespaces = src.m_namespaces;
m_node = src.m_node;
}
CXmlStackNamespaces()
{
}
CXmlStackNamespaces(const XmlUtils::CXmlNode& node)
{
m_node = node;
}
CXmlStackNamespaces& operator=(const CXmlStackNamespaces& src)
{
m_namespaces = src.m_namespaces;
m_node = src.m_node;
return *this;
}
CXmlStackNamespaces GetById(const std::string& id)
{
return GetByIdRec(*this, id);
}
CXmlStackNamespaces GetByIdRec(CXmlStackNamespaces& stack, const std::string& id)
{
if (stack.m_node.GetAttributeA("Id") == id)
return stack;
CXmlStackNamespaces ret = stack;
std::vector<std::wstring> _names;
std::vector<std::wstring> _values;
ret.m_node.ReadAllAttributes(_names, _values);
NSStringUtils::CStringBuilder oBuilder;
oBuilder.WriteString(L" ");
for (std::vector<std::wstring>::iterator i = _names.begin(), j = _values.begin(); i != _names.end(); i++, j++)
{
if (i->find(L"xmlns") == 0)
{
oBuilder.WriteString(*i);
oBuilder.WriteString(L"=\"");
oBuilder.WriteEncodeXmlString(*j);
oBuilder.WriteString(L"\"");
}
}
if (oBuilder.GetCurSize() != 1)
ret.m_namespaces += oBuilder.GetData();
XmlUtils::CXmlNodes oNodes;
if (stack.m_node.GetChilds(oNodes))
{
int nCount = oNodes.GetCount();
for (int i = 0; i < nCount; i++)
{
oNodes.GetAt(i, ret.m_node);
CXmlStackNamespaces _retRecursion = ret.GetByIdRec(ret, id);
if (_retRecursion.m_node.IsValid())
return _retRecursion;
}
}
return CXmlStackNamespaces();
}
std::string GetXml()
{
std::wstring sXml = m_node.GetXml();
if (!m_namespaces.empty())
{
std::wstring sName = m_node.GetName();
std::wstring sXmlFind = L"<" + sName + L" ";
if (0 == sXml.find(sXmlFind))
sXml.replace(0, sXmlFind.length(), L"<" + sName + L" " + m_namespaces + L" ");
}
return U_TO_UTF8(sXml);
}
};
public:
COOXMLSignature()
{
m_valid = OOXML_SIGNATURE_INVALID;
m_guid = "";
m_cert = NULL;
}
~COOXMLSignature()
{
RELEASEOBJECT(m_cert);
}
public:
int GetValid()
{
return m_valid;
}
std::string GetGuid()
{
return m_guid;
}
ICertificate* GetCertificate()
{
return m_cert;
}
std::string GetImageValidBase64()
{
return m_sImageValidBase64;
}
std::string GetImageInvalidBase64()
{
return m_sImageInvalidBase64;
}
public:
void Check()
{
// 1) get cert
XmlUtils::CXmlNode oNodeCert = m_node.ReadNode(L"KeyInfo").ReadNode(L"X509Data").ReadNode(L"X509Certificate");
if (!oNodeCert.IsValid())
{
m_valid = OOXML_SIGNATURE_NOTSUPPORTED;
return;
}
m_cert = new CCertificate();
if (!m_cert->LoadFromBase64Data(U_TO_UTF8(oNodeCert.GetText())))
{
m_valid = OOXML_SIGNATURE_NOTSUPPORTED;
return;
}
// 2) Objects
XmlUtils::CXmlNodes nodesReferences;
m_node.ReadNode(L"SignedInfo").GetNodes(L"Reference", nodesReferences);
CXmlStackNamespaces stack(m_node);
int nCount = nodesReferences.GetCount();
for (int i = 0; i < nCount; i++)
{
XmlUtils::CXmlNode nodeRef;
nodesReferences.GetAt(i, nodeRef);
std::string sId = nodeRef.GetAttributeA("URI");
if (0 == sId.find("#"))
sId = sId.substr(1);
CXmlStackNamespaces _stack = stack.GetById(sId);
std::string sTmp = _stack.GetXml();
XML_UNUSED(sTmp);
}
}
friend class COOXMLVerifier;
};
class COOXMLVerifier
{
public:
std::wstring m_sFolder;
std::vector<COOXMLSignature*> m_arSignatures;
public:
COOXMLVerifier(const std::wstring& sFolder)
{
m_sFolder = sFolder;
if (!NSFile::CFileBinary::Exists(m_sFolder + L"/_xmlsignatures/origin.sigs"))
return;
XmlUtils::CXmlNode oContentTypes;
if (!oContentTypes.FromXmlFile(m_sFolder + L"/[Content_Types].xml"))
return;
XmlUtils::CXmlNodes oOverrides = oContentTypes.GetNodes(L"Override");
int nCount = oOverrides.GetCount();
for (int i = 0; i < nCount; i++)
{
XmlUtils::CXmlNode node;
oOverrides.GetAt(i, node);
if (node.GetAttributeA("ContentType") != "application/vnd.openxmlformats-package.digital-signature-xmlsignature+xml")
continue;
std::wstring sFile = m_sFolder + node.GetAttribute("PartName");
XmlUtils::CXmlNode nodeSig;
if (!nodeSig.FromXmlFile(sFile))
continue;
if (nodeSig.GetName() != L"Signature")
continue;
COOXMLSignature* pSignature = new COOXMLSignature();
pSignature->m_node = nodeSig;
pSignature->Check();
m_arSignatures.push_back(pSignature);
}
}
~COOXMLVerifier()
{
for (std::vector<COOXMLSignature*>::iterator i = m_arSignatures.begin(); i != m_arSignatures.end(); i++)
{
COOXMLSignature* v = *i;
RELEASEOBJECT(v);
}
m_arSignatures.clear();
}
};
#endif //_XML_OOXMLVERIFIER_H_

View File

@ -0,0 +1,17 @@
#ifndef _XMLSIGNER_CERTIFICATE_H_
#define _XMLSIGNER_CERTIFICATE_H_
#ifdef WIN32
#include "XmlSigner_mscrypto.h"
#define CCertificate CCertificate_mscrypto
#endif
#if defined(_LINUX) && !defined(_MAC)
#endif
#ifdef _MAC
#endif
#endif // _XMLSIGNER_CERTIFICATE_H_

View File

@ -8,6 +8,9 @@
#include <vector>
#include <map>
#define OOXML_HASH_ALG_SHA1 0
#define OOXML_HASH_ALG_INVALID 1
class ICertificate
{
public:
@ -27,17 +30,26 @@ public:
virtual std::string GetCertificateHash() = 0;
public:
virtual std::string Sign(std::string sXml) = 0;
virtual std::string GetHash(unsigned char* pData, unsigned int nSize) = 0;
virtual std::string GetHash(std::string& sXml) = 0;
virtual std::string GetHash(std::wstring& sXmlFile) = 0;
virtual bool Verify(std::string& sXml, std::string& sXmlSignature) = 0;
virtual std::string Sign(std::string sXml) = 0;
virtual std::string GetHash(unsigned char* pData, unsigned int nSize, int nAlg) = 0;
virtual std::string GetHash(std::string& sXml, int nAlg) = 0;
virtual std::string GetHash(std::wstring& sXmlFile, int nAlg) = 0;
virtual bool Verify(std::string& sXml, std::string& sXmlSignature, int nAlg) = 0;
virtual bool LoadFromBase64Data(const std::string& data) = 0;
virtual int ShowCertificate() = 0;
virtual bool LoadFromBase64Data(const std::string& data) = 0;
virtual int ShowCertificate() = 0;
public:
virtual bool ShowSelectDialog() = 0;
static int GetOOXMLHashAlg(const std::string& sAlg)
{
if ("http://www.w3.org/2000/09/xmldsig#rsa-sha1" == sAlg ||
"http://www.w3.org/2000/09/xmldsig#sha1" == sAlg)
return OOXML_HASH_ALG_SHA1;
return OOXML_HASH_ALG_INVALID;
}
};
#endif // _XMLSIGNER_BASE_H_

View File

@ -93,7 +93,7 @@ public:
virtual std::string GetCertificateHash()
{
return GetHash(m_context->pbCertEncoded, (unsigned int)m_context->cbCertEncoded);
return GetHash(m_context->pbCertEncoded, (unsigned int)m_context->cbCertEncoded, OOXML_HASH_ALG_SHA1);
}
public:
@ -166,8 +166,11 @@ public:
return sReturn;
}
virtual std::string GetHash(unsigned char* pData, unsigned int nSize)
virtual std::string GetHash(unsigned char* pData, unsigned int nSize, int nAlg)
{
if (nAlg == OOXML_HASH_ALG_INVALID)
return "";
BOOL bResult = TRUE;
DWORD dwKeySpec = 0;
HCRYPTHASH hHash = NULL;
@ -181,7 +184,7 @@ public:
if (!bResult)
return "";
bResult = CryptCreateHash(hCryptProv, CALG_SHA1, 0, 0, &hHash);
bResult = CryptCreateHash(hCryptProv, GetHashId(nAlg), 0, 0, &hHash);
if (!bResult)
{
CryptReleaseContext(hCryptProv, 0);
@ -231,12 +234,12 @@ public:
return sReturn;
}
virtual std::string GetHash(std::string& sXml)
virtual std::string GetHash(std::string& sXml, int nAlg)
{
return GetHash((BYTE*)sXml.c_str(), (DWORD)sXml.length());
return GetHash((BYTE*)sXml.c_str(), (DWORD)sXml.length(), nAlg);
}
virtual std::string GetHash(std::wstring& sXmlFile)
virtual std::string GetHash(std::wstring& sXmlFile, int nAlg)
{
BYTE* pFileData = NULL;
DWORD dwFileDataLen = 0;
@ -245,13 +248,13 @@ public:
if (0 == dwFileDataLen)
return "";
std::string sReturn = GetHash(pFileData, dwFileDataLen);
std::string sReturn = GetHash(pFileData, dwFileDataLen, nAlg);
RELEASEARRAYOBJECTS(pFileData);
return sReturn;
}
virtual bool Verify(std::string& sXml, std::string& sXmlSignature)
virtual bool Verify(std::string& sXml, std::string& sXmlSignature, int nAlg)
{
DWORD dwKeySpec = 0;
HCRYPTHASH hHash = NULL;
@ -263,7 +266,7 @@ public:
if (!bResult)
return FALSE;
bResult = CryptCreateHash(hCryptProv, CALG_SHA1, 0, 0, &hHash);
bResult = CryptCreateHash(hCryptProv, GetHashId(nAlg), 0, 0, &hHash);
if (!bResult)
{
@ -344,6 +347,17 @@ private:
for(BYTE* p = dst + size - 1; p >= dst; ++src, --p)
(*p) = (*src);
}
ALG_ID GetHashId(int nAlg)
{
switch (nAlg)
{
case OOXML_HASH_ALG_SHA1:
return CALG_SHA1;
default:
return CALG_SHA1;
}
}
};
#endif // _XMLSIGNER_MSCRYPTO_H_

View File

@ -1,5 +1,6 @@
#include "../../src/XmlSigner_mscrypto.h"
#include "../../src/XmlCertificate.h"
#include "../../src/OOXMLSigner.h"
#include "../../src/OOXMLVerifier.h"
#pragma comment (lib, "crypt32.lib")
#pragma comment (lib, "cryptui.lib")
@ -7,58 +8,38 @@
void main(void)
{
if (false)
{
BYTE* pData = NULL;
DWORD dwDataLen = 0;
bool bRes = NSFile::CFileBinary::ReadAllBytes(L"D:\\cert2.bin", &pData, dwDataLen);
if (!bRes)
return;
PCCERT_CONTEXT context = CertCreateCertificateContext(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, pData, dwDataLen);
if (!context)
{
RELEASEARRAYOBJECTS(pData);
return;
}
BOOL result = CryptUIDlgViewContext(CERT_STORE_CERTIFICATE_CONTEXT, context, NULL, NULL, 0, NULL);
result;
if (context)
CertFreeCertificateContext(context);
RELEASEARRAYOBJECTS(pData);
return;
}
if (false)
{
xmlLoadExtDtdDefaultValue = XML_DETECT_IDS | XML_COMPLETE_ATTRS;
xmlSubstituteEntitiesDefault(1);
std::string sXmlCan = CXmlCanonicalizator::Execute(L"D:\\1.xml", XML_C14N_1_0);
NSFile::CFileBinary::SaveToFile(L"D:\\2.xml", UTF8_TO_U(sXmlCan));
return;
}
//std::wstring sFolderOOOXML = NSFile::GetProcessDirectory() + L"/ImageStamp";
//std::wstring sSignId = L"{39B6B9C7-60AD-45A2-9F61-40C74A24042E}";
std::wstring sFolderOOXML = L"D:\\555";
std::wstring sSignId = L"{9792D33F-AB37-4E5B-A465-481B9465818B}";
CCertificate_mscrypto oCertificate;
if (!oCertificate.ShowSelectDialog())
return;
if (false)
{
std::wstring sSignId = L"{9792D33F-AB37-4E5B-A465-481B9465818B}";
COOXMLSigner oOOXMLSigner(sFolderOOXML, &oCertificate);
CCertificate oCertificate;
if (!oCertificate.ShowSelectDialog())
return;
oOOXMLSigner.SetGuid(sSignId);
oOOXMLSigner.SetImageValid(NSFile::GetProcessDirectory() + L"/../../../resources/valid.png");
oOOXMLSigner.SetImageInvalid(NSFile::GetProcessDirectory() + L"/../../../resources/invalid.png");
COOXMLSigner oOOXMLSigner(sFolderOOXML, &oCertificate);
oOOXMLSigner.Sign();
oOOXMLSigner.SetGuid(sSignId);
oOOXMLSigner.SetImageValid(NSFile::GetProcessDirectory() + L"/../../../resources/valid.png");
oOOXMLSigner.SetImageInvalid(NSFile::GetProcessDirectory() + L"/../../../resources/invalid.png");
oOOXMLSigner.Sign();
}
else
{
COOXMLVerifier oVerifier(sFolderOOXML);
size_t nCount = oVerifier.m_arSignatures.size();
for (std::vector<COOXMLSignature*>::iterator i = oVerifier.m_arSignatures.begin(); i != oVerifier.m_arSignatures.end(); i++)
{
COOXMLSignature* pSign = *i;
XML_UNUSED(pSign);
}
XML_UNUSED(nCount);
}
}