`

Openssl和PKCS#11的故事

阅读更多

1.1   What to do

通过Openssl和PKCS#11接口,使用USBKEY中的私钥和证书来签发一个下级证书。

1.2              背景

数字证书颁发过程一般为:用户首先产生自己的密钥对,并将公共密钥及部分个人身份信息传送给认证中心。认证中心在核实身份后,将执行一些必要的步 骤,以确信请求确实由用户发送而来,然后,认证中心将发给用户一个数字证书,该证书内包含用户的个人信息和他的公钥信息,同时还附有认证中心的签名信息。

 

 

 

 

一个标准的X.509数字证书包含以下一些内容:

证书的版本信息;

证书的序列号,每个证书都有一个唯一的证书序列号;

证书所使用的签名算法;

证书的发行机构名称,命名规则一般采用X.500格式;

证书的有效期,现在通用的证书一般采用UTC时间格式,它的计时范围为1950-2049;

证书所有人的名称,命名规则一般采用X.500格式;

证书所有人的公开密钥;

证书发行者对证书的签名。

 

简而言之,CA从PKCS#10证书请求(或者P7格式)中读取用户信息和公钥信息,使用这些信息封装成一个X.509格式(可能是不同版本,比较 普遍是V3),此时唯一没有包括的是证书发行者对证书的签名,此时使用CA的私钥进行签名,得到签名值后CA将其填充到X.509相对应的结构中去,一个 X.509证书宝宝就此诞生了。

 

此处唯一不同的是CA的公私钥对和证书都存放在USBKEY中(当然也能存放在加密机或加密卡中),所以将通过USBKEY的PKCS#11接口完成上述操作,而证书相关操作就由Openssl代劳了。

 

1.3              正题

第一、使用Usbkey向某个CA申请一个证书

通过下面的命令来验证,第一组公私钥对和证书是签名证书,第二组是加密证书。可以很明显地看出他们是通过Csp方式操作整个证书申请过程的。

C:\Program Files\Smart card bundle>pkcs11-tool.exe --module DMPKCS11.dll –O

Certificate Object, type = X.509 cert

label:      cert addey by CSP

ID:         37af001ddbd525e640ca3c3f6d78b009741d1f48

Public Key Object; RSA 1024 bits

label:      pub key addey by CSP

ID:         37af001ddbd525e640ca3c3f6d78b009741d1f48

Usage:      encrypt, verify

Private Key Object; RSA

label:      private key addey by CSP

ID:         37af001ddbd525e640ca3c3f6d78b009741d1f48

Usage:      decrypt, sign

Certificate Object, type = X.509 cert

label:      cert addey by CSP

ID:         ab268f4320a426b4a6ce70d757cd11fcd83b8ddd

Public Key Object; RSA 1024 bits

label:      pub key addey by CSP

ID:         ab268f4320a426b4a6ce70d757cd11fcd83b8ddd

Usage:      encrypt, verify

Private Key Object; RSA

label:      private key addey by CSP

ID:         ab268f4320a426b4a6ce70d757cd11fcd83b8ddd

Usage:      decrypt, sign

 

第二、生成PKCS#11的证书请求

这里直接使用Java程序生成一个证书请求。

import java.io.OutputStreamWriter;

import java.security.KeyPair;

import java.security.KeyPairGenerator;

 

import javax.security.auth.x500.X500Principal;

 

import org.bouncycastle.jce.PKCS10CertificationRequest;

import org.bouncycastle.openssl.PEMWriter;

 

/**

* Generation of a basic PKCS #10 request.

*/

public class PKCS10CertRequestExample

{

    public static PKCS10CertificationRequest generateRequest(

        KeyPair pair)

        throws Exception

    {

        return new PKCS10CertificationRequest(

                "SHA256withRSA",

                new X500Principal("C=CN,ST=上海,L=上海,O=火星,OU=北极,CN=超人"),

                pair.getPublic(),

                null,

                pair.getPrivate());

    }

   

    public static void main(

        String[]    args)

        throws Exception

    {

        // create the keys

        KeyPairGenerator kpGen = KeyPairGenerator.getInstance("RSA", "BC");

        kpGen.initialize(1024, Utils.createFixedRandom());

        KeyPair          pair = kpGen.generateKeyPair();

        PKCS10CertificationRequest request = generateRequest(pair);

        PEMWriter        pemWrt = new PEMWriter(new OutputStreamWriter(System.out));

        pemWrt.writeObject(request);

        pemWrt.close();

    }

}

 

 

证书请求

-----BEGIN CERTIFICATE REQUEST-----

MIIBoDCCAQkCAQAwYjEPMA0GA1UEAwwG6LaF5Lq6MQ8wDQYDVQQLDAbljJfmnoEx

DzANBgNVBAoMBueBq+aYnzEPMA0GA1UEBwwG5LiK5rW3MQ8wDQYDVQQIDAbkuIrm

tbcxCzAJBgNVBAYTAkNOMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCw7iyU

/8p1lCxnJifdqxNYO1cTVg35BBtscQsrtug9Br3Vge/kNX9KC5xOGhdcK1IDjl3d

1CGsRtnb4dEFqtkjKWQ1z5WZxXWoVfkqwP3AJg8y10BhiiDqPPbn3II4o8Nc+bvz

tDm32HbNXcyXWLR5aEJx1FiJYdDmDbRbgGrcawIDAQABMA0GCSqGSIb3DQEBCwUA

A4GBAJSr2pe1LJp++gSWAc7yVufbnYXG3QgzIdoEUhP1I/3LNeqUYyuTaL/fTgAF

oEjTvwOlAVizcve8qiD9/ApY+MtjgRKFDbZYnkC3mRgJTDxV3WzDmdj4YEQGIUVG

O+XRfiWP132n9N3aI6gaJVj2m7Zu56akrE3F2c4kawZL/aIK

-----END CERTIFICATE REQUEST-----

 

第三、程序签发

1. engine_pkcs11的使用方式

       使用openssl调用USBKEY的PKCS#11接口,可以通过OpenSC项目的engine_pkcs11接口。原本使用编写openssl配置 文件方式(见[1]),但是就是无法使用,两次调用ListEngine()都无法发现pkcs11 engine的影子。

Openssl.conf 内容:

 

openssl_conf = openssl_def

 

[openssl_def]

engines = engine_section

 

[engine_section]

pkcs11 = pkcs11_section

 

[pkcs11_section]

engine_id = pkcs11

dynamic_path = "C:\\Program Files\\Smart card bundle\\engine_pkcs11.dll"

MODULE_PATH = C:\\Windows\\System32\\DMPKCS11.dll

init = 0

 

[req]

distinguished_name = req_distinguished_name

 

[req_distinguished_name]

 

可以通过下面命令验证配置文件并没有写错,openssl识别出了pkcs11 engine,并且生成了证书请求。

C:\Program Files\Smart card bundle>openssl req -config openssl.conf -engine pkcs11 -new -key id_37af001ddbd525e640ca3c3f6d78b009741d1f48 -keyform engine -out req.pem -text -x509 -subj "/CN=Andreas Jellinghaus"

engine "pkcs11" set.

PKCS#11 token PIN:

 

所以最后还是使用动态调用的方式导入pkcs11 engine,即ENGINE_load_dynamic。所以两次调用ListEngine()后发现, dynamic engine导入pkcs11 engine后就会被其替换。

导入前

id: dynamic, name: Dynamic engine loading support

导入后

id: pkcs11, name: pkcs11 engine

 

2. 导出USBKEY中的CA证书

需要导出CA证书,这是因为CA需要填充X.509格式中的证书的发行机构名称。

通过” LOAD_CERT_CTRL”命令来获取证书,输入的参数为证书的表示。

"slot_0-id_37af001ddbd525e640ca3c3f6d78b009741d1f48"

slot_0     PKCS#11 表示的第一个插槽(一个插槽配一个Token)

id_37af001ddbd525e640ca3c3f6d78b009741d1f48 证书的Id号(同一组公私钥对和证书这个ID是相同的),这个ID可以通过pkcs11-tools获得。

命令返回的parms.cert就指向一个X.509结构的证书。

但是必须要注意的是导出证书前,必须设置过正确的PIN

    struct {

       const char * cert_id;

       X509 * cert;

    } parms;

 

    parms.cert_id = "slot_0-id_37af001ddbd525e640ca3c3f6d78b009741d1f48";

    parms.cert = NULL;

    ENGINE_ctrl_cmd(e, "LOAD_CERT_CTRL", 0, &parms, NULL, 1);

 

 

3. 证书请求

通过JAVA生成的证书请求,直接复制粘贴到工程目录下的文本文件certreq.txt即可,并且需要包含BEGIN/END部分。

 

4. 从证书请求中获取用户信息

    //设置证书的主体名称,req就是刚刚生成的请求证书

    X509_set_subject_name(m_pClientCert, X509_REQ_get_subject_name(req));

    //设置证书的公钥信息

    X509_set_pubkey(m_pClientCert, X509_PUBKEY_get(req->req_info->pubkey));

 

5. 设置证书的签发者信息

    //设置证书的签发者信息,m_pCACert是CA证书

    X509_set_issuer_name(m_pClientCert, X509_get_subject_name(m_pCACert));

 

6. 证书签名

注意这里采用的是sha1的摘要算法,当然也可使用MD5

    //设置签名值

    // EVP_sha1 是否可以设置成别的,如EVP_md5

    // 这样一份X509证书就生成了,下面的任务就是对它进行编码保存。

    X509_sign(m_pClientCert, m_pCAKey, EVP_sha1());

 

此处还有些补充的内容,为了验证X509_sign调用PKCS#11接口的情况,自己实现了一个PKCS#11的包装壳(68个导出函数),实现 时注意C_GetFunctionList应该指向本包装壳的函数,不然错误的使用实际的C_GetFunctionList作返回结构便也就失去意义 了。X509_sign的调用方式还是不同的,java中如果使用SHA1WithRSA传入到PKCS#11接口的C_Sign或者 C_SignUpdate的数据是完整的明文,但是X509_sign传入的是一个ASN.1 Sequence的一个结构,结构中包含待签名数据的摘要散列。

举例来说:

 

待加密的数据是Hello World! ,在C_Sign传入的数据中就可以发现Hello World!的SHA-1的摘要散列。

待加密:Hello World!

SHA-1: 2EF7BDE608CE5404E97D5F042F95F89F1C232871

 

C_Sign:

30 21 30 09 06 05 2b 0e 03 02 1a 05 00 04 14 2e f7 bd e6 08 ce 54 04 e9 7d 5f 04 2f 95 f8 9f 1c 23 28 71

 

使用ASN.1dump来观察就看的更加清楚了。

 

从X509_sign的实现也可以看的这一点,在RSA_Sign之前首先进行摘要算法,并且这个摘要并不使用PKCS#11中的接口函数,直接使用Openssl自己的摘要算法,所以传入到最后的只是明文摘要散列了。

int X509_sign(X509 *x, EVP_PKEY *pkey, const EVP_MD *md)
{
//先进行ret->cert_info->signature,以及ret->sig_alg的设置;
inl=i2d_X509_CINF(ret->cert_info,NULL);//求出证书编码后的长度
buf_in=(unsigned char *)OPENSSL_malloc((unsigned int)inl);//申请空间
outll=outl=EVP_PKEY_size(pkey1);
buf_outl=(unsigned char *)OPENSSL_malloc((unsigned int)inl);
if ((buf_in == NULL) ││ (buf_outl== NULL))
    {
    outl=0;
    goto err;
    }
    p=buf_in;//p与buf-in共享一段地址
    i2d_X509_CINF(ret->cert_info,&p);//将证书编码存入buf-in
    EVP_MD_CTX_init(&ctxl);//初始化
    EVP_SignInit(&ctxl,dgst);//将需要使用的摘要算法存入ctxl中
    EVP_SignUpdate(&ctxl,(unsigned char *)buf_in,inl);//存入证书的编码值
    EVP_DigestFinal(&ctxl,&(m[0]),&m_len);//求取编码的长度为m_len摘要值存入m中
    RSA_sign(ctxl->digest->type,m,m_len,buf_out,outl,pkey->pkey.rsa)//求取摘要值的签名值,最后将长度为outl的签名值存入buf-out。

    ......


 

7. 最后生成的证书

USBKEY 中包含证书是向三级CA申请的,所以处于第四级,使用第四级证书来签发新证书,超人宝宝就只能到第五级去了(也许是第五项修炼吧)。

其实还是个问题,第四级证书报“此证书似乎对于所选的目的是有效。”,出现此问题的原因嵌入在消息中的签名证书链包含一个无效的交叉引用,估计第四级是一个用户证书,要消除这个感叹号,第四级证书的证书用法中应该包含Digital Signature, Certificate Signing, Off-line CRL Signing, CRL Signing (86)这几项

8.完整代码

// SignWithOpenSSL.cpp : 定义控制台应用程序的入口点。

//

 

#include "stdafx.h"

#include <windows.h>

 

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

 

#include <openssl/engine.h>

#include <openssl/conf.h>

#include <openssl/pem.h>

#include <openssl/x509.h>

#include <openssl/rsa.h>

#include <openssl/x509v3.h>

 

#define OPENSSL_LOAD_CONF

 

#define UC_ENGINE_SOPATH "C:\\Program Files\\Smart card bundle\\engine_pkcs11.dll"

#define UC_EXPECTED_ENGINE_ID "pkcs11"

#define UC_ENGINE_MODULEPATH "C:\\Windows\\System32\\DMPKCS11.dll"

 

// 列出当前所有的engine

/*

ENGINE *ENGINE_get_first(void);

ENGINE *ENGINE_get_last(void);

ENGINE *ENGINE_get_next(ENGINE *e);

ENGINE *ENGINE_get_prev(ENGINE *e);

*/

void ListEngine()

{

    ENGINE *current;

    current = ENGINE_get_first();

    if( NULL != current )

    {

       printf("id: %s, name: %s\n",

           ENGINE_get_id(current),

           ENGINE_get_name(current));

 

       while( NULL != (current = ENGINE_get_next(current)))

       {

           printf("id: %s, name: %s\n",

              ENGINE_get_id(current),

              ENGINE_get_name(current));

       }

    }

}

 

/*存储证书*/

int save_cert(X509 *pCert, char *pCertFile)

{

    BIO *pbio;

 

    if(NULL == pCert || NULL == pCertFile)

    {

       return -1;

    }

 

    pbio = BIO_new_file(pCertFile, "w");

    if(NULL == pbio)

    {

       return -1;

    }

 

    if(!i2d_X509_bio(pbio, pCert))

    {

       printf("save_cert:call PEM_write_bio_X509 error ");

       return -1;

    }

 

    printf("Bingo, New Cert is borned\n");

 

    BIO_free(pbio);

    return 0;

}

 

void add_subject_entity(X509_NAME *pSubjectName, char *key, char *value)

{

    int nid;

    X509_NAME_ENTRY *ent;

    if( (nid =OBJ_txt2nid(key)) == NID_undef )

    {

       printf(" add_subject_entity:concert nid error");

       return ;

    }

 

    ent = X509_NAME_ENTRY_create_by_NID( NULL, nid, MBSTRING_UTF8,

       (unsigned char*)value, -1);

    if(ent == NULL)

    {

       printf("add_subject_entity:create ent error");

       return;

    }

 

    if(X509_NAME_add_entry(pSubjectName, ent, -1, 0) != 1)

    {

       printf("add_subject_entity:add to subjectname error");

       return;

    }

    return;

}

 

int CreateX509Cert(X509 *m_pCACert, EVP_PKEY *m_pCAKey)

{

    // 读取证书请求

    BIO           *in;

    X509_REQ      *req=NULL,**req2=NULL;

 

    in = BIO_new_file("certreq.txt","r");

    req = PEM_read_bio_X509_REQ(in,NULL,NULL,NULL);

    if( req == NULL )

    {

       printf("DER Decode Error!\n");

    }

    else

    {

       printf("DER Decode Success!\n");

    }

 

    // 使用usbkey中的私钥进行签名

    X509 *m_pClientCert;

    m_pClientCert = X509_new();

    //设置版本号

    X509_set_version(m_pClientCert, 2);

    //设置证书序列号,这个sn就是CA中心颁发的第N份证书

    ASN1_INTEGER_set(X509_get_serialNumber(m_pClientCert),100);

    //设置证书开始时间

    X509_gmtime_adj(X509_get_notBefore(m_pClientCert),0);

    //设置证书结束时间

    X509_gmtime_adj(X509_get_notAfter(m_pClientCert), (long)60*60*24);

    //设置证书的主体名称,req就是刚刚生成的请求证书

    X509_set_subject_name(m_pClientCert, X509_REQ_get_subject_name(req));

    //设置证书的公钥信息

    X509_set_pubkey(m_pClientCert, X509_PUBKEY_get(req->req_info->pubkey));

    //设置证书的签发者信息,m_pCACertCA证书

    X509_set_issuer_name(m_pClientCert, X509_get_subject_name(m_pCACert));

 

    //设置扩展项目

    X509V3_CTX ctx;

    X509V3_set_ctx(&ctx, m_pCACert, m_pClientCert, NULL, NULL, 0);

    X509_EXTENSION *x509_ext = X509_EXTENSION_new();

    x509_ext = X509V3_EXT_conf(NULL, &ctx, "HELLO", "HELLO");

    X509_add_ext(m_pClientCert,x509_ext,-1);

 

    //设置签名值

    // EVP_sha1 是否可以设置成别的,如EVP_md5

    // 这样一份X509证书就生成了,下面的任务就是对它进行编码保存。

    X509_sign(m_pClientCert, m_pCAKey, EVP_sha1());

 

    // 输出证书

    save_cert(m_pClientCert, "d:\\test.cer");

 

    return 0;

}

 

int main(int argc, CHAR* argv[])

{

    ENGINE *e;

    const char *engine_id = "pkcs11";

    const char *key_id = "37af001ddbd525e640ca3c3f6d78b009741d1f48";

    UI_METHOD *ui_method = NULL;

    EVP_PKEY *priv_key;

    void *cb_data;

    const char *config_name = NULL;

    BIO *bio_err=NULL;

 

    /* Load the config file */

    //OPENSSL_config(config_name); // 不使用Openssl0.9.8e的配置文件来导入PKCS11

 

    ENGINE_load_dynamic();

 

    ListEngine();

 

    printf("\nLoading Dynamic...\n");

 

    /* Register engine */

    printf("Registering enginen");

    e = ENGINE_by_id("dynamic");

    if(!e) {

       /* the engine isn't available */

       printf("The engine isn't available\n");

       return 0;

    }

 

 

    //int ENGINE_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)(void));

 

    ENGINE_ctrl(e, ENGINE_CTRL_SET_LOGSTREAM, 0, bio_err, 0);

    // 设置engine_pkcs11的路径

    ENGINE_ctrl_cmd_string(e, "SO_PATH", UC_ENGINE_SOPATH, 0);

 

    ENGINE_ctrl_cmd_string(e, "ID", UC_EXPECTED_ENGINE_ID, 0);

 

    ENGINE_ctrl_cmd_string(e, "LIST_ADD", "1", 0);

 

    ENGINE_ctrl_cmd_string(e, "LOAD", NULL, 0);

    // 设置USBKEY厂商PKCS#11实现的路径

    ENGINE_ctrl_cmd_string(e, "MODULE_PATH", UC_ENGINE_MODULEPATH, 0);

 

    // 设置PIN

    if(!ENGINE_ctrl_cmd_string(e, "PIN", "111111", 0)){

       printf("Error sending PIN to = engine");

       ENGINE_free(e);

       return 0;

    }  

 

    ListEngine();

 

    if(!ENGINE_init(e)) {

       /* the engine couldn't initialise, release 'e' */

       printf("The engine couldn't initialise\n");

       ENGINE_free(e);

       return 0;

    }

 

    if(!ENGINE_register_RSA(e)){

       /* This should only happen when 'e' can't initialise, but the previous

       * statement suggests it did. */

       printf("This should not happen\n");

       abort();

    }

 

    // 直接从usb-key中导入证书,但必须初始化后。

    struct {

       const char * cert_id;

       X509 * cert;

    } parms;

 

    parms.cert_id = "slot_0-id_37af001ddbd525e640ca3c3f6d78b009741d1f48";

    parms.cert = NULL;

    ENGINE_ctrl_cmd(e, "LOAD_CERT_CTRL", 0, &parms, NULL, 1);

 

    // Load private key

    printf("Loading private key\n");

    priv_key = ENGINE_load_private_key(e, key_id, ui_method, &cb_data);

 

    // 产生证书

    CreateX509Cert(parms.cert, priv_key);

 

    // Release the functional reference from ENGINE_init()

    ENGINE_finish(e);

    // Release the structural reference from ENGINE_by_id()

    ENGINE_free(e);

 

    return 0;

}

 

1.4              参考

[1] DNSSEC Signers and OpenSSL

[END]

分享到:
评论

相关推荐

    按PKCS#10数据格式封装PKCS#10数据

    在生成PKCS#10请求时,通常需要使用特定的库或工具,如OpenSSL,将证书请求的各个部分按照PKCS#10的标准结构组合起来,然后使用私钥进行签名。这个过程确保了请求的完整性和安全性。 在提供的压缩包文件"ParseP10...

    企业微信支付到个人银行卡(PKCS#1格式的公钥转为PKCS#8格式)

    PKCS(Public Key Cryptography Standards)是由RSA安全公司提出的公钥加密标准,其中PKCS#1主要定义了RSA公钥和私钥的格式,而PKCS#8则定义了通用的非对称密钥的编码格式,支持多种加密算法,包括RSA。 在微信支付...

    使用数字证书进行PKCS#7数字签名

    越来越多的应用需要我们使用USB接口数字证书进行PKCS#7数字签名。本文分别介绍了使用微软CryptoAPI方式和OpenSSL Engine方式进行数字签名。特别地,提出了OpenSSL Engine简化方式,这种方式更为灵活方便易行。

    openssl_engine_pkcs11_src

    总结来说,OpenSSL Engine PKCS#11源码是理解和实现OpenSSL与PKCS#11设备交互的重要参考资料。它展示了如何在OpenSSL中创建和配置一个自定义引擎,以支持PKCS#11标准,同时也提供了测试代码以验证引擎的功能和性能。...

    libp11:PKCS#11 包装库

    OpenSSL 库的 pkcs11 引擎插件允许以半透明的方式访问 PKCS#11 模块。 该项目的 wiki 页面位于 ,包括错误跟踪器和源浏览器。 PKCS#11 PKCS#11 API 是一个抽象 API,用于对加密对象(例如私钥)执行操作,而无需...

    Openssl Engine pkcs11 示例程序

    从OpenSSL的0.9.7版,Engine机制集成到了OpenSSL的内核中,成为了OpenSSL不可缺少的一部分。 Engine机制目的是为了使OpenSSL能够透明地使用第三方提供的软件加密库或者硬件加密设备进行...支持PKCS#11接口的Engine接口

    PKCS#1 java 语言实现参考 V1.0

    基于BigInteger类用java封装的PKCS#1 v2.1 全算法实现,模块与规范一一对应。包含 I2OSP OS2IP RSAEP RSADP RSASP1 RSAVP1 RSAES-OAEP RSAES-PKCS1_v1_5 RSASSA-PSS RSASSA-PKCS1-v1_5 以及 MGF SourceAlgrithm等...

    qsslkey-p11:使用PKCS#11的QSslKey

    本示例说明如何使用OpenSSL( )和engine_pkcs11( )来使QSslSocket使用私钥和HSM的证书( )使用PKCS#11( )。 要测试此示例,您将需要OpenSSL标头和库,binary_pkcs11的二进制版本以及PKCS#11模块(所用设备...

    php实现PKCS#7算法加解密

    在中国银行的支付和报文验签场景中,PKCS#7算法被广泛应用于保证数据的完整性和机密性。本文将详细介绍如何使用PHP来实现PKCS#7的加解密过程。 首先,PKCS#7的主要特点是它可以处理任意长度的数据,并且支持填充...

    openssl 生成ca证书 pkcs12 pem格式转换

    OpenSSL 生成 CA 证书 PKCS#12 PEM 格式转换 OpenSSL 是目前最流行的 SSL 密码库工具,其提供了一个通用、健壮、功能完备的工具套件,用以支持 SSL/TLS 协议的实现。 OpenSSL 工具箱中包含了大量实用的命令和选项,...

    pkcs1与pkcs8证书互相转换.rar

    这里提到的"pkcs1与pkcs8证书互相转换"是指在处理公钥证书时,如何在PKCS#1和PKCS#8格式之间进行转换。这两种格式都是用于存储和交换数字证书的标准,但它们的结构和用途有所不同。 **PKCS#1**,也称为RSA密钥格式...

    AES_ECB_PKCS5Padding openssl加解密方式

    由于业务需求需要对接java接口,对方接口采用AES/ECB/PKCS5Padding加密技术,还经过,16进制转换,php端采用openssl加解密方式。调试可以访问http://tool.chacuo.net/cryptaes

    pkcs11js:PKCS#11 2.3接口的Node.js实现。 (关键字

    PKCS#11(也称为CryptoKI或PKCS11)是用于与诸如智能卡和硬件安全模块(HSM)之类的硬件加密设备进行交互的标准接口。 该文件是根据PKCS#11 2.30规范开发的,在我们创建此文件时尚未提供2.40标头,应该足够容易...

    pkcs7.rar_openssl 签名_openssl pkcs7_openssl数字签名_openssl签名_pkcs7签

    利用OpenSSL PKCS7进行数字签名的示例代码,仅供参考

    openssl之pkcs7 - squallxun的日志 - 网易博客.png

    openssl之pkcs7 - squallxun的日志 - 网易博客.png

    根据PEM(PKCS#8格式)文件生成DSA对象的项目源代码

    [b]将传统格式的私钥转换成PKCS#8格式的(java使用的是PKCS#8格式的私钥)[/b] openssl pkcs8 -topk8 -inform PEM -in dsa_private_temp_key.pem -outform PEM -nocrypt -out dsa_private_key.pem c) 生成公钥 ...

    PKCS11导入证书.rar_pkcs11_PKCS11示例_源码

    PKCS11,全称Public Key Cryptography Standards #11,是RSA安全公司制定的一套标准,用于定义加密硬件(如智能卡、硬件安全模块HSM)与软件应用程序之间的接口。这个标准允许软件应用程序透明地使用加密硬件进行...

    opencryptoki:适用于Linux的PKCS#11库和工具。 包括支持TPM和IBM加密硬件的令牌以及软件令牌

    openCryptoki版本3.15实现了PKCS#11规范版本3.0。 该软件包包括几个加密令牌:CCA,ICA,TPM,SWToken,ICSF和EP11。 有关openCryptoki的更深入概述,请参阅 要求: IBM ICA-需要libica库版本3.3.0或更高版本...

    RSA pkcs1 pkcs8转换工具.zip

    PKCS(Public Key Cryptography Standards)是由RSA安全公司制定的一系列加密标准,其中PKCS#1和PKCS#8涉及到RSA密钥的存储格式。 PKCS#1主要定义了RSA公钥和私钥的编码格式,它包括两种主要的编码方式:RSA加密...

    graphene:用于与TypeScript中的Node的PKCS#11 PKCS11 CryptoKI交互的简单层。 (关键字

    PKCS#11(也称为CryptoKI或PKCS11)是用于与诸如智能卡和硬件安全模块(HSM)之类的硬件加密设备进行交互的标准接口。 它紧密地包装了库,但是在合理的地方尝试使用看起来像“ node.crypto”的形式。 已通过以下...

Global site tag (gtag.js) - Google Analytics