• crypto_2


     1,解码CERT_INFO结构
       给定一个证书,第一步是调用函数CertCreateCertificateContext解码证书BLOB。当这个函数被调用,那么产生一个编码证书的复制品,创建一个CERT_CONETXT类型的结构和一个CERT_INFO类型的结构。一个certificate_context包含一个原始证书BLOB,一个CERT_CONETXT类型的结构以及一个CERT_INFO类型的结构。下面我们具体看看CERT_CONETXT以及CERT_INFO的结构(wincrypt.h):
      typedef struct _CERT_CONTEXT {
       DWORD dwCertEncodingType;
       BYTE *pbCertEncoded;
       DWORD cbCertEncoded;
       PCERT_INFO pCertInfo;
       HCERTSTORE hCertStore;
      } CERT_CONTEXT, *PCERT_CONTEXT;
      typedef const CERT_CONTEXT *PCCERT_CONTEXT;
      typedef struct _CERT_INFO {
       DWORD dwVersion;
       CRYPT_INTEGER_BLOB SerialNumber;
       CRYPT_ALGORITHM_IDENTIFIER SignatureAlgorithm;
       CERT_NAME_BLOB Issuer;
       FILETIME NotBefore;
       FILETIME NotAfter;
       CERT_NAME_BLOB Subject;
       CERT_PUBLIC_KEY_INFO SubjectPublicKeyInfo;
       CRYPT_BIT_BLOB IssuerUniqueId;
       CRYPT_BIT_BLOB SubjectUniqueId;
       DWORD cExtension;
       PCERT_EXTENSION rgExtension;
      } CERT_INFO, *PCERT_INFO;
      typedef struct _CERT_EXTENSIONS {
       DWORD cExtension;
       PCERT_EXTENSION rgExtension;
      } CERT_EXTENSIONS, *PCERT_EXTENSIONS;
      由上面的三个结构可以明显的看出证书的存储过程。(具体参数意思可以由参数名看出来)
       2,编码一个CERT_INFO结构
       编码过程和解码过程是相反的,下面事例如何增加签发者到CERT_INFO结构中。
       1,创建一个包含签发者名字的字符串。
       2,创建一个CERT_RDN_ATTR结构的数组,它初始化后能够包含刚刚创建的字符串。
       3,创建一个CERT_RDN结构的数组,它包含刚刚初始化的CERT_RDN_ATTR结构的数组
       4,创建一个CERT_NAME_INFO结构指向刚刚创建的CERT_RDN结构的数组的指针
       5,调用CryptEncodeObject函数来获取输出编码后BLOB的长度。
       6,为BLOB分配内存空间
       7,再次调用CryptEncodeObject函数,将有关编码信息写入
       8,设置CERT_INFO结构中的Issuer.cbData为第5步得到的长度,设置Issuer.pbData为第6步得到的地址,那么现在签发者就存在于CERT_INFO结构中了。
       添加一个编码后的扩展信息到CERT_INFO结构中
       1,初始化一个扩展信息结构。
       2,调用CryptEncodeObject,来获取所需空间大小。
       3,分配空间
       4,再次调用CryptEncodeObject来获取编码后的信息。
       5,创建一个CERT_EXTENSION结构数组
       6,初始化CERT_EXTENSION,并且在CERT_EXTENSION中添加刚刚编码后的信息。
       7,初始化CERT_INFO结构的rgExtension,并且把他指向CERT_EXTENSION结构数组(

     

    接上:

    1.CERT_RDN_ATTR 结构体

    typedef struct _CERT_RDN_ATTR {
    LPSTR
    pszObjId;
    DWORD
    dwValueType;
    CERT_RDN_VALUE_BLOB
    Value; } CERT_RDN_ATTR,
    *PCERT_RDN_ATTR;
    pszObjId:对象标识符,用于标识证书属性,具体可以查看MSDN中的解析,也可以查看wincrypt.h文件查看相应的定义。譬如szOID_STATE_OR_PROVINCE_NAME,表示省名。
    dwValueType:对成员Value的解析,取值查看MSDN,当主要是初始化证书属性时,Value的值主要是一些字符串时,该值可以为CERT_RDN_PRINTABLE_STRING,表示可以打印的字符串。
    Value:一个结构体,在这里初始化证书属性。
    typedef struct _CRYPTOAPI_BLOB {
    DWORD
    cbData;
    BYTE*
    pbData; } ,其中cbData表示大小,pbData指向一个内存空间。
     
    2.CERT_RDN 结构体:The CERT_RDN structure contains a relative distinguished name (RDN) consisting of an array of CERT_RDN_ATTR structures.
    typedef struct _CERT_RDN {
    DWORD
    cRDNAttr;
    PCERT_RDN_ATTR
    rgRDNAttr; } CERT_RDN,
    *PCERT_RDN;
    参数:cRDNAttr:rgRDNAttr数组元素的个数;rgRDNAttr:指向CERT_RDN_ATTR结构元素的数组地址。
    3.CERT_NAME_INFO 结构体:The CERT_NAME_INFO structure contains subject or issuer names.The information is represented as an array of CERT_RDN structures.
    typedef struct _CERT_NAME_INFO {
    DWORD
    cRDN;
    PCERT_RDN
    rgRDN; } CERT_NAME_INFO,
    *PCERT_NAME_INFO;
    参数:同上差不多。
    4.CERT_REQUEST_INFO 证书请求结构体:这个结构体包含证书请求的主体,主体公钥,属性块等信息,这些信息都是经过编码的。
    typedef struct _CERT_REQUEST_INFO {
    DWORD
    dwVersion;
    CERT_NAME_BLOB
    Subject;
    CERT_PUBLIC_KEY_INFO
    SubjectPublicKeyInfo;
    DWORD
    cAttribute;
    PCRYPT_ATTRIBUTE
    rgAttribute; } CERT_REQUEST_INFO,
    *PCERT_REQUEST_INFO;
     
    参数:dwVersion:证书版本号,可以为CERT_V1等,根据属性扩展情况,符合不同版本证书;Subject:证书主题;SubjectPublicKeyInfo:证书主题中的公钥信息;cAttribute:rgAttribute数组元素个数,可以为0;rgAttribute:属性参数数组,可以为NULL;
    以上信息都是要经过编码后的信息来填充的。
    5.CryptSignAndEncodeCertificate函数,用来创建自签名证书
    BOOL WINAPI CryptSignAndEncodeCertificate(
      __in          HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProvOrNCryptKey,
      __in          DWORD dwKeySpec,
      __in          DWORD dwCertEncodingType,
      __in          LPCSTR lpszStructType,
      __in          const void* pvStructInfo,
      __in          PCRYPT_ALGORITHM_IDENTIFIER pSignatureAlgorithm,
      __in          const void* pvHashAuxInfo,
      __out         PBYTE pbEncoded,
      __in_out      DWORD* pcbEncoded
    );
    参数:1,CSP句柄;2,指明公钥是来自签名公钥还是交换公钥,可以为AT_KEYEXCHANGE或者AT_SIGNATURE之一;3,指明编码类型,可以为X509_ASN_ENCODING;4,结构体类型,和第5个参数配合起来使用,可以为X509_CERT_CRL_TO_BE_SIGNED或者X509_CERT_REQUEST_TO_BE_SIGNED或者X509_CERT_TO_BE_SIGNED或者X509_KEYGEN_REQUEST_TO_BE_SIGNED,意思可以查看MSDN。
    6,签名算法结构体,指明签名算法,算法标识可以为szOID_RSA_MD5RSA 或者szOID_RSA_SHA1RSA 或者szOID_X957_SHA1DSA ;7,可以不用,设为NULL;8,签名后数据的长度,当设为NULL时,可以用来求数据的长度;9,用于存放数据的内存空间。
  • 相关阅读:
    Cannot find class [org.springframework.http.converter.json.MappingJacksonHttpMessageConverter]
    HTTP的长连接和短连接
    Nginx(三)nginx 反向代理
    Nginx(四)nginx 负载均衡
    postgresql 数据库 INSERT 或 UPDATE 大量数据时速度慢的原因分析
    低层次父母,喜欢不停地“讲道理”,而高层次父母,会做2件事
    oracle数据库数据量如何计算,怎么查看oracle数据库数据量大小?
    Git的eclipse插件(下载、抓取、提交、恢复、比较)
    Linux 上 定时备份postgresql 数据库的方法
    Nginx(二)nginx.conf 配置文件
  • 原文地址:https://www.cnblogs.com/lzjsky/p/1842053.html
Copyright © 2020-2023  润新知