使用x509证书加密soap消息

时间:2016-12-07 10:25:32

标签: c++ soap openssl x509certificate x509

我正在尝试了解x509证书如何与openssl和加密soap消息一起使用。我正在使用lib-wsdlpull库来修改soap消息。所以我添加了重现此示例标题的方法:http://www.ibm.com/support/knowledgecenter/SSGMCP_5.3.0/com.ibm.cics.ts.webservices.doc/wsSecurity/dfhws_soapmsg_signed.html

根据这个例子,我需要:

  1. 二进制安全性令牌包含X.509证书的base64binary编码。此编码包括SOAP消息的预期接收者用于验证签名的公钥。
  2. 我有以下代码,我相信给我X.509证书

    #include "openssl/bio.h"
    #include "openssl/ssl.h"
    #include "openssl/err.h"
    #include "openssl/x509.h"
    
    #include <iostream>
    #include <cstdlib>
    #include <string>
    
    using namespace std;
    
    char *base64(const unsigned char *input, unsigned int length)
    {
            BIO *bmem, *b64;
            BUF_MEM *bptr;
    
            b64 = BIO_new(BIO_f_base64());
            bmem = BIO_new(BIO_s_mem());
            b64 = BIO_push(b64, bmem);
            BIO_write(b64, input, length);
            BIO_flush(b64);
            BIO_get_mem_ptr(b64, &bptr);
    
            char *buff = (char *)malloc(bptr->length);
            memcpy(buff, bptr->data, bptr->length - 1);
            buff[bptr->length - 1] = 0;
    
            BIO_free_all(b64);
    
            return buff;
    }
    
    /*
     * generates a key pair
     * */
    EVP_PKEY* generateKeyPair(){
            int bits = 2048;        /* number of bits for the key - 2048 is a sensible value */
    
            EVP_PKEY * pkey = EVP_PKEY_new();
            RSA* rsa = RSA_new();
    
            BIGNUM *bne = BN_new();
            BN_set_word(bne, RSA_F4);       /* exponent - RSA_F4 is defined as 0x10001L */
            if ( RSA_generate_key_ex(rsa, bits, bne, NULL) == 0 ){
                    BN_free(bne);
                    RSA_free(rsa);
    
                    return NULL;
            }
    
            BN_free(bne);
    
            EVP_PKEY_assign_RSA(pkey, rsa);
    
            return pkey;
    }
    
    X509* createCertificate(){
        X509* x509 = X509_new();
    
        if ( x509 == NULL ){
                return NULL;
        }
    
        ASN1_INTEGER_set(X509_get_serialNumber(x509), 1);
        X509_gmtime_adj(X509_get_notBefore(x509), 0);
        X509_gmtime_adj(X509_get_notAfter(x509), 31536000L);
    
        return x509;
    }
    
    void setPublicKey(X509* x509, EVP_PKEY* pkey){
            X509_set_pubkey(x509, pkey);
    }
    
    void signCertificate(X509* x509, EVP_PKEY* pkey){
            X509_sign(x509, pkey, EVP_sha1());
    }
    
    void writePrivateKey( EVP_PKEY* pkey, const char* fileName ){
    
        FILE * f;
        f = fopen(fileName, "wb");
        PEM_write_PrivateKey(
                        f,                  /* write the key to the file we've opened */
                        pkey,               /* our key from earlier */
                        NULL, /* default cipher for encrypting the key on disk */
                        NULL,       /* passphrase required for decrypting the key on disk */
                        10,                 /* length of the passphrase string */
                        NULL,               /* callback for requesting a password */
                        NULL                /* data to pass to the callback */
                        );
    }
    
    void writeCertificate( X509* x509, const char* fileName ){
    
        FILE * f;
        f = fopen(fileName, "wb");
        PEM_write_X509(
                        f,   /* write the certificate to the file we've opened */
                        x509 /* our certificate */
                      );
    }
    
    const EVP_MD* digestMessage( const char* digestName, const std::string& strToEncode, unsigned char **digestValue, unsigned int& digestLen ){
            const EVP_MD *digest = EVP_get_digestbyname(digestName);
        EVP_MD_CTX *mdctx = EVP_MD_CTX_create();
        EVP_DigestInit_ex(mdctx, digest, NULL);
    
        EVP_DigestUpdate(mdctx, strToEncode.c_str(), strToEncode.size());
    
        EVP_DigestFinal_ex(mdctx, *digestValue, &digestLen);
        EVP_MD_CTX_destroy(mdctx);
    
        return digest;
    }
    
    int main(){
    
        SSL_load_error_strings();
        ERR_load_BIO_strings();
        OpenSSL_add_all_algorithms();
        OpenSSL_add_all_digests();
    
        EVP_PKEY * pkey = generateKeyPair();
        if ( pkey == NULL ){
                puts("Something went wrong when generating private key");
    
                return -1;
        }
    
        X509* x509 = createCertificate();
        if ( x509 == NULL ){
                puts("Something went wrong when generating certificate");
    
                return -1;
        }
    
        setPublicKey( x509, pkey );
        signCertificate( x509, pkey );
    
        writePrivateKey( pkey, "privatekey.pem" );
        writeCertificate( x509, "cert.pem" );
    

    据我所知,在cert.pem中我有X.509证书

    下一步是 3.消息摘要的值。

    我有以下代码

    unsigned char* digestValue = new unsigned char[10000];
            unsigned int digestLen = 0;
            std::string textToSign = "test32131654564627863276837243286324eroi5t5twutaergeahnuihnuigyniguyfgnufutfgbuuuyggygykgygjhggyjjkjkggjhkjggjjkgjkggyjkhgyjkggyg6567578576tyuiytrfv76igrtuigrtuigbrtgrbtuuutuftffgfffff ytffhfhgfhfhgfhgfhfhgfyty54u5654u5rgu5rfguytrfrttttttyyyttgh   gf";
            textToSign += textToSign;
            textToSign += textToSign;
            textToSign += textToSign;
            textToSign += textToSign;
            textToSign += textToSign;
            textToSign += textToSign;
            textToSign += textToSign;
            textToSign += textToSign;
            textToSign += textToSign;
            textToSign += textToSign;
            textToSign += textToSign;
            textToSign += textToSign;
            textToSign += textToSign;
            textToSign += textToSign;
            textToSign += textToSign;
            textToSign += textToSign;
            textToSign += textToSign;
            textToSign += textToSign;
            textToSign += textToSign;
            textToSign += textToSign;
            textToSign += textToSign;
            textToSign += textToSign;
    
    const EVP_MD* digest = digestMessage( "sha1", textToSign, &digestValue, digestLen );
    

    所有我不理解和缺失的是最后一步 4.然后使用用户的私钥加密摘要值,并将其作为签名值

    包含在此处

    我不知道处理这个问题...有人可以帮忙吗?

    我写了这个

    X509_digest(x509, digest, digestValue, &digestLen);
    

    但我不确定它是否有意义......

0 个答案:

没有答案