Pergunta

Eu tenho um aplicativo C / C ++ e eu preciso para criar um certificado X509 pem contendo tanto um público e uma chave privada. O certificado pode ser auto-assinado ou não assinado, não importa.

Eu quero fazer isso dentro de um aplicativo, não a partir de linha de comando.

funções que OpenSSL vai fazer isso por mim? Qualquer código de exemplo é um bônus!

Foi útil?

Solução

Você vai precisar para se familiarizar com a terminologia e os mecanismos de primeira.

Um X.509 Certificado , por definição, não inclui uma chave privada. Em vez disso, é uma versão assinada-CA da chave pública (juntamente com qualquer atribui as puts CA para a assinatura). O formato PEM realmente só suporta o armazenamento separado da chave e o certificado -. Embora você possa então concatenar os dois

Em qualquer caso, você vai precisar para invocar mais de 20 funções diferentes da API OpenSSL para criar uma chave e um certificado auto-assinado. Um exemplo está na própria fonte OpenSSL, em demos / x509 / mkcert.c

Para uma resposta mais detalhada, consulte o Nathan Osman explicação abaixo.

Outras dicas

Eu percebo que esta é uma resposta muito tarde (e longo). Mas, considerando o quão bem esta questão parece classificação de resultados de pesquisas, achei que talvez valesse a pena escrever uma resposta decente para.

Muito do que você vai ler abaixo é emprestado de este demo e os docs OpenSSL. O código a seguir aplica-se a C e C ++.


Antes que possamos realmente criar um certificado, é preciso criar uma chave privada. OpenSSL fornece a estrutura EVP_PKEY para armazenar uma chave privada independente de algoritmo na memória. Esta estrutura é declarada em openssl/evp.h mas é incluído por openssl/x509.h (que vamos precisar mais tarde) para que você realmente não precisa incluir explicitamente o cabeçalho.

A fim de alocar uma estrutura EVP_PKEY, usamos EVP_PKEY_new :

EVP_PKEY * pkey;
pkey = EVP_PKEY_new();

Há também uma função correspondente para libertar a estrutura - EVP_PKEY_free - que aceita um único argumento:. A estrutura EVP_PKEY inicializado acima

Agora, precisamos gerar uma chave. Para o nosso exemplo, vamos gerar uma chave RSA. Isso é feito com o RSA_generate_key função que é declarada em openssl/rsa.h. Esta função devolve um ponteiro para uma estrutura RSA.

A simples invocação da função pode ter esta aparência:

RSA * rsa;
rsa = RSA_generate_key(
    2048,   /* number of bits for the key - 2048 is a sensible value */
    RSA_F4, /* exponent - RSA_F4 is defined as 0x10001L */
    NULL,   /* callback - can be NULL if we aren't displaying progress */
    NULL    /* callback argument - not needed in this case */
);

Se o valor de retorno de RSA_generate_key é NULL, então algo deu errado. Se não, então agora temos uma chave RSA, e podemos atribuí-la a nossa estrutura EVP_PKEY de mais cedo:

EVP_PKEY_assign_RSA(pkey, rsa);

A estrutura RSA será liberado automaticamente quando a estrutura EVP_PKEY é liberado.


Agora, para o próprio certificado.

OpenSSL usa a estrutura X509 para representar um certificado x509 na memória. A definição para esta estrutura está em openssl/x509.h. A primeira função que vamos precisar é X509_new . Seu uso é relativamente simples:

X509 * x509;
x509 = X509_new();

Como foi o caso com EVP_PKEY, existe uma função correspondente para libertar a estrutura -. X509_free

Agora, precisamos definir algumas propriedades do certificado usando algumas funções X509_*:

ASN1_INTEGER_set(X509_get_serialNumber(x509), 1);

Isso define o número de série do nosso certificado para '1'. Alguns servidores HTTP de código aberto se recusam a aceitar um certificado com um número de série de '0', que é o padrão. O próximo passo é especificar o período de tempo durante o qual o certificado é realmente válido. Fazemos isso com as seguintes duas chamadas de função:

X509_gmtime_adj(X509_get_notBefore(x509), 0);
X509_gmtime_adj(X509_get_notAfter(x509), 31536000L);

A primeira linha define a propriedade notBefore do certificado para a hora atual. (A função X509_gmtime_adj adiciona o número especificado de segundos para o tempo atual - neste caso, nenhum.) A segunda linha define a propriedade notAfter do certificado para 365 dias a partir de agora (60 segundos * 60 minutos * 24 horas * 365 dias)

Agora, precisamos definir a chave pública para o nosso certificado usando a chave que gerou anteriormente:

X509_set_pubkey(x509, pkey);

Uma vez que este é um certificado auto-assinado, vamos definir o nome do emissor para o nome do assunto. O primeiro passo nesse processo é fazer com que o nome do assunto:

X509_NAME * name;
name = X509_get_subject_name(x509);

Se você já criou um certificado auto-assinado na linha de comando antes, você provavelmente se lembra ser perguntado por um código de país. Aqui é onde nós fornecê-lo juntamente com a organização ( 'O') e nome comum (NC):

X509_NAME_add_entry_by_txt(name, "C",  MBSTRING_ASC,
                           (unsigned char *)"CA", -1, -1, 0);
X509_NAME_add_entry_by_txt(name, "O",  MBSTRING_ASC,
                           (unsigned char *)"MyCompany Inc.", -1, -1, 0);
X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC,
                           (unsigned char *)"localhost", -1, -1, 0);

(estou usando o valor 'CA' aqui porque eu sou canadense e esse é o nosso código do país. Observe também que o parâmetro # 4 precisa ser expressos de forma explícita a um unsigned char *.)

Agora podemos realmente definir o nome do emitente:

X509_set_issuer_name(x509, name);

E finalmente estamos prontos para executar o processo de assinatura. Chamamos X509_sign com a chave geramos anteriormente. O código para isso é dolorosamente simples:

X509_sign(x509, pkey, EVP_sha1());

Note que estamos usando o algoritmo de hash SHA-1 para assinar a chave. Isso difere da mkcert.c demo que eu mencionei no início desta resposta, que usa MD5.


Agora temos um certificado auto-assinado! Mas nós ainda não terminamos - precisamos escrever esses arquivos para o disco. Felizmente OpenSSL nos cobriu lá também com as funções PEM_* que são declaradas em openssl/pem.h. O primeiro vamos precisar é PEM_write_PrivateKey para salvar a nossa chave privada.

FILE * f;
f = fopen("key.pem", "wb");
PEM_write_PrivateKey(
    f,                  /* write the key to the file we've opened */
    pkey,               /* our key from earlier */
    EVP_des_ede3_cbc(), /* default cipher for encrypting the key on disk */
    "replace_me",       /* 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 */
);

Se você não quiser criptografar a chave privada, então simplesmente passar NULL para o terceiro e quarto parâmetro acima. De qualquer maneira, você definitivamente vai querer garantir que o arquivo não é mundialmente legível. (Para os usuários do Unix, isto significa chmod 600 key.pem.)

Ufa! Agora estamos para baixo para uma função - precisamos escrever o certificado para o disco. A função que precisamos para isso é PEM_write_X509:

FILE * f;
f = fopen("cert.pem", "wb");
PEM_write_X509(
    f,   /* write the certificate to the file we've opened */
    x509 /* our certificate */
);

E estamos a fazer! Esperamos que as informações nesta resposta é suficiente para lhe dar uma idéia de como funciona tudo, embora nós mal arranhamos a superfície do OpenSSL.

Para aqueles interessados ??em ver o que todo o código acima parece em uma aplicação real, eu tenho jogado juntos uma Gist (escrito em C ++) que você pode ver aqui .

Qualquer chance de fazer isso através de uma chamada system de dentro de seu aplicativo? Várias boas razões para fazer isso:

  • Licenciamento: Chamando o executável openssl indiscutivelmente o separa de sua aplicação e pode proporcionar certas vantagens. Disclaimer:. Consultar um advogado sobre este

  • Documentação:. OpenSSL vem com fenomenal documentação de linha de comando que simplifica muito uma ferramenta potencialmente complicado

  • Testability: você pode exercer OpenSSL a partir da linha de comando até que você entender exatamente como criar seus certificados. Há uma grande quantidade de opções; esperar gastar cerca de um dia sobre isso até que você obter todos os detalhes direito. Depois disso, é trivial para incorporar o comando em seu aplicativo.

Se você optar por usar a API, verifique a lista dos desenvolvedores openssl-dev em www.openssl.org.

Boa sorte!

tutorial muito simples criar certificados digitais http://publib.boulder.ibm.com/infocenter/rsthelp/v8r0m0/index.jsp?topic=/com.ibm.rational.test.lt.doc /topics/tcreatecertopenssl.html

Sobre a execução desses comandos do seu código eu não tenho certeza.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top