Add method for cert&key generation

This commit is contained in:
Oleg Korshul
2023-07-28 12:09:51 +03:00
parent c2748fcff4
commit 3217ac7d51
5 changed files with 203 additions and 33 deletions

View File

@ -42,6 +42,8 @@ namespace NSCertificate
OPENSSL_DECL std::wstring GetSignatureMethod(const int& nAlg);
OPENSSL_DECL ICertificate* CreateInstance(const int& type = CERTIFICATE_ENGINE_TYPE_DEFAULT);
OPENSSL_DECL ICertificate* GenerateByAlg(const std::string& key_alg, const std::map<std::wstring, std::wstring>& props = std::map<std::wstring, std::wstring>());
};
#endif // _XML_CERTIFICATE_COMMON_H_

View File

@ -3,6 +3,7 @@
#include <string>
#include <vector>
#include <map>
#include "../../../common/base_export.h"
#ifdef COMMON_OPENSSL_BUILDING_INTERNAL

View File

@ -317,6 +317,21 @@ namespace NSCertificate
return NULL;
}
ICertificate* GenerateByAlg(const std::string& key_alg, const std::map<std::wstring, std::wstring>& props)
{
#ifdef SUPPORT_OPENSSL
CCertificate_openssl* pCert = new CCertificate_openssl();
bool bIsGenerated = pCert->Generate(key_alg, props);
if (!bIsGenerated)
{
delete pCert;
return NULL;
}
return pCert;
#endif
return NULL;
}
};
#ifdef SUPPORT_OPENSSL

View File

@ -24,6 +24,8 @@
#include <openssl/evp.h>
#include <openssl/conf.h>
#include <map>
const EVP_MD* Get_EVP_MD(int nAlg)
{
switch (nAlg)
@ -121,6 +123,148 @@ public:
EVP_PKEY_FREE(m_key);
}
bool Generate(const std::string& key_alg, const std::map<std::wstring, std::wstring>& props = std::map<std::wstring, std::wstring>())
{
EVP_PKEY_CTX* pctx = nullptr;
int nRsaKeyLen = 0;
if (key_alg == "ed25519")
{
pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_ED25519, NULL);
m_alg = OOXML_HASH_ALG_ED25519;
}
else if (key_alg == "x25519")
{
pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_X25519, NULL);
m_alg = OOXML_HASH_ALG_ED448;
}
else if (0 == key_alg.find("rsa"))
{
pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL);
std::string sKeyLen = key_alg.substr(3);
nRsaKeyLen = 2048;
if (!sKeyLen.empty())
nRsaKeyLen = std::stoi(sKeyLen);
m_alg = OOXML_HASH_ALG_SHA256;
}
else
return false;
EVP_PKEY_keygen_init(pctx);
if (0 != nRsaKeyLen && EVP_PKEY_CTX_set_rsa_keygen_bits(pctx, nRsaKeyLen) <= 0)
return false;
EVP_PKEY_keygen(pctx, &m_key);
m_cert = X509_new();
X509_set_version(m_cert, 2);
ASN1_STRING* serialNumber = X509_get_serialNumber(m_cert);
if (serialNumber)
{
const int nBytesCount = 16;
unsigned char pSerialNumber[nBytesCount];
RAND_bytes(pSerialNumber, nBytesCount);
if (1 != ASN1_STRING_set(serialNumber, pSerialNumber, nBytesCount) == 1)
ASN1_INTEGER_set(serialNumber, 1);
}
X509_gmtime_adj(X509_get_notBefore(m_cert), 0);
X509_gmtime_adj(X509_get_notAfter(m_cert), 31536000L);
if (X509_set_pubkey(m_cert, m_key) == 0)
{
if (NULL != m_cert)
X509_free(m_cert);
m_cert = NULL;
if (NULL != m_key)
EVP_PKEY_free(m_key);
m_key = NULL;
EVP_PKEY_CTX_free(pctx);
return false;
}
X509_NAME* name_record = X509_get_subject_name(m_cert);
std::wstring sC = L"US";
std::wstring sO = L"Ascensio System SIA";
std::wstring sCN = L"AOSign Certificate";
std::map<std::wstring, std::wstring>::const_iterator iter_prop = props.find(L"C");
if (iter_prop != props.end())
sC = iter_prop->second;
iter_prop = props.find(L"O");
if (iter_prop != props.end())
sO = iter_prop->second;
iter_prop = props.find(L"CN");
if (iter_prop != props.end())
sCN = iter_prop->second;
std::string sC_A = U_TO_UTF8(sC);
std::string sO_A = U_TO_UTF8(sO);
std::string sCN_A = U_TO_UTF8(sCN);
X509_NAME_add_entry_by_txt(name_record, "C", MBSTRING_ASC, (unsigned char *)sC_A.c_str(), -1, -1, 0);
X509_NAME_add_entry_by_txt(name_record, "O", MBSTRING_ASC, (unsigned char *)sO_A.c_str(), -1, -1, 0);
X509_NAME_add_entry_by_txt(name_record, "CN", MBSTRING_ASC, (unsigned char *)sCN_A.c_str(), -1, -1, 0);
X509_set_issuer_name(m_cert, name_record);
if (!props.empty())
{
std::string sAdditions = "";
for (std::map<std::wstring, std::wstring>::const_iterator iter = props.begin(); iter != props.end(); iter++)
{
std::string sKey = U_TO_UTF8(iter->first);
std::string sValue = U_TO_UTF8(iter->second);
string_replace(sKey, ";", "&#59;");
string_replace(sKey, "=", "&#61;");
string_replace(sValue, ";", "&#59;");
sAdditions += (sKey + "=" + sValue + ";");
}
if (!sAdditions.empty())
{
//const int nid_user = OBJ_create("1.2.3", "key", "value");
ASN1_OCTET_STRING* oDataAdditions = ASN1_OCTET_STRING_new();
int nError = ASN1_OCTET_STRING_set(oDataAdditions, (unsigned const char*)sAdditions.c_str(), (int)sAdditions.length());
X509_EXTENSION* ext = X509_EXTENSION_create_by_NID(nullptr, NID_subject_alt_name, false, oDataAdditions);
nError = X509_add_ext(m_cert, ext, -1);
X509_EXTENSION_free(ext);
}
}
const EVP_MD* pDigest = Get_EVP_MD(this->GetHashAlg());
if (NULL == pDigest)
pDigest = EVP_md_null();
if (X509_sign(m_cert, m_key, pDigest) == 0)
{
if (NULL != m_cert)
X509_free(m_cert);
m_cert = NULL;
if (NULL != m_key)
EVP_PKEY_free(m_key);
m_key = NULL;
EVP_PKEY_CTX_free(pctx);
return false;
}
EVP_PKEY_CTX_free(pctx);
return true;
}
virtual int GetType()
{
return CERTIFICATE_ENGINE_TYPE_OPENSSL;

View File

@ -1,5 +1,5 @@
#include "../../../common/File.h"
#include "../include/XmlCertificate.h"
#include "../include/CertificateCommon.h"
#include "../include/OOXMLSigner.h"
#include "../include/OOXMLVerifier.h"
@ -12,56 +12,64 @@
int main()
{
std::wstring sTestDir = NSFile::GetProcessDirectory() + L"/../../";
ICertificate* pCertificate = NULL;
std::wstring sTestDir = NSFile::GetProcessDirectory() + L"/../../";
#ifdef USE_MS_CRYPTO
//ICertificate* pCertificate = NSCertificate::FromFiles(sTestDir + L"keys/key.key", "", sTestDir + L"keys/cert.crt", "");
// TODO: Load sertificate from store
std::map<std::wstring, std::wstring> properties;
properties.insert(std::make_pair(L"email", L"sign@onlyoffice.com"));
properties.insert(std::make_pair(L"phone", L"+00000000000"));
std::wstring sNameTest = L"NameTest";
std::wstring sValueTest = L"ValueTest";
properties.insert(std::make_pair(sNameTest, sValueTest));
#else
//ICertificate* pCertificate = NSCertificate::GenerateByAlg("rsa2048", properties);
ICertificate* pCertificate = NSCertificate::GenerateByAlg("ed25519", properties);
pCertificate = ICertificate::CreateInstance();
pCertificate->FromFiles(sTestDir + L"keys/key.key", "", sTestDir + L"keys/cert.crt", "");
#endif
unsigned char* pSignData = NULL;
unsigned int nSignDataLen = 0;
std::string sSignData = "Hello world!";
bool bRes = pCertificate->SignPKCS7((unsigned char*)sSignData.c_str(), (unsigned int)sSignData.length(), pSignData, nSignDataLen);
BYTE* pDataDst = NULL;
unsigned long nLenDst = 0;
RELEASEARRAYOBJECTS(pSignData);
BYTE* pDataDst = NULL;
unsigned long nLenDst = 0;
#ifdef USE_SIGN
#if 0
COOXMLSigner oSigner(sTestDir + L"file", pCertificate);
oSigner.Sign(pDataDst, nLenDst);
COOXMLSigner oSigner(sTestDir + L"file", pCertificate);
oSigner.Sign(pDataDst, nLenDst);
#else
BYTE* pDataSrc = NULL;
unsigned long nLenSrc = 0;
NSFile::CFileBinary::ReadAllBytes(sTestDir + L"/file.docx", &pDataSrc, nLenSrc);
BYTE* pDataSrc = NULL;
unsigned long nLenSrc = 0;
NSFile::CFileBinary::ReadAllBytes(sTestDir + L"/file.docx", &pDataSrc, nLenSrc);
COOXMLSigner oSigner(pDataSrc, nLenSrc, pCertificate);
oSigner.Sign(pDataDst, nLenDst);
RELEASEARRAYOBJECTS(pDataSrc);
COOXMLSigner oSigner(pDataSrc, nLenSrc, pCertificate);
oSigner.Sign(pDataDst, nLenDst);
RELEASEARRAYOBJECTS(pDataSrc);
NSFile::CFileBinary oFileDst;
oFileDst.CreateFileW(sTestDir + L"/file2.docx");
oFileDst.WriteFile(pDataDst, nLenDst);
oFileDst.CloseFile();
NSFile::CFileBinary oFileDst;
oFileDst.CreateFileW(sTestDir + L"/file2.docx");
oFileDst.WriteFile(pDataDst, nLenDst);
oFileDst.CloseFile();
#endif
#endif
RELEASEARRAYOBJECTS(pDataDst);
RELEASEARRAYOBJECTS(pDataDst);
#ifdef USE_VERIFY
#if 1
COOXMLVerifier oVerifier(sTestDir + L"file");
int nCount = oVerifier.GetSignatureCount();
for (int i = 0; i < nCount; i++)
{
COOXMLSignature* pSign = oVerifier.GetSignature(i);
pSign->Check();
}
COOXMLVerifier oVerifier(sTestDir + L"file");
int nCount = oVerifier.GetSignatureCount();
for (int i = 0; i < nCount; i++)
{
COOXMLSignature* pSign = oVerifier.GetSignature(i);
pSign->Check();
}
#endif
#endif
delete pCertificate;
return 0;
delete pCertificate;
return 0;
}