Emitir a partir de um CSR
Quando você mesmo gera o par de chaves, no seu servidor ou no navegador do usuário, você envia ao Amplia só uma requisição de assinatura de certificado (CSR), e ele devolve o certificado.
Fluxo
- Gere o par de chaves e o CSR. Faça isso antes de criar o pedido, para que uma falha na chave não consuma um pedido.
- Crie o pedido. O subject do certificado vem dos parâmetros do pedido, nunca do CSR.
- Emita o certificado:
POST /api/v2/certificatescom o id do pedido, o CSR e a mídia da chave. - Mantenha a chave privada onde ela foi gerada, e o certificado junto dela.
Os samples geram a chave e o CSR com o PKI Express, depois emitem o certificado e guardam os dois no servidor:
- Node.js
- Java
- PHP
- Python
const {KeyGenerator} = require('pki-express');
const {KeyMedia } = require('amplia-client/lib/enums');
const keyGenerator = new KeyGenerator({
keySize: req.body.keySize,
genCsr: true
});
let genKey = await keyGenerator.generate();
let generatedKey = genKey.getKey();
let cert = await client.issueCertificate(order.getId(), genKey.getCsr(), KeyMedia.PC);
let certId = cert.getId();
// WARNING: It is highly RECOMMENDED to ENCRYPT the key before storing
// in your database.
StorageMock.storeSync(generatedKey, certId, '.json');
StorageMock.storeSync(cert.getContentRaw(), certId, '.cer');
KeyGenerator keyGenerator = new KeyGenerator();
keyGenerator.setKeySize(2048);
keyGenerator.setKeyFormat(KeyFormats.JSON);
keyGenerator.setGenCsr(true);
KeyGenerationResult genKey = keyGenerator.generate();
Certificate cert = client.issueCertificate(order.getId(), genKey.getCsr());
// WARNING: It is highly RECOMMENDED to ENCRYPT the key before storing in your database.
StorageMock.storeKey(genKey.getKey().getBytes(), ".json", cert.getId());
StorageMock.storeKey(cert.getContent(), ".cer", cert.getId());
use Lacuna\PkiExpress\KeyGenerator;
use Lacuna\PkiExpress\SupportedKeySizes;
use Lacuna\PkiExpress\KeyFormats;
$keyGenerator = new KeyGenerator();
$keyGenerator->keySize = SupportedKeySizes::S2048;
$keyGenerator->keyFormat = KeyFormats::JSON;
$keyGenerator->genCsr = true;
$genKey = $keyGenerator->generate();
$cert = $client->issueCertificate($order->getId(), $genKey->csr);
StorageMock::storeKey($genKey->key, ".json", $cert->id);
StorageMock::storeKey($cert->getContentRaw(), ".cer", $cert->id);
from pkiexpress import KeyGenerator, Pkcs12Generator, SupportedKeySizes
key_generator = KeyGenerator()
key_generator.key_size = SupportedKeySizes.S2048
key_generator.gen_csr = True
gen_key = key_generator.generate()
cert = client.issue_certificate(order.id, gen_key.csr)
pkcs12_generator = Pkcs12Generator()
pkcs12_generator.key = gen_key.key
pkcs12_generator.set_cert_file_from_base64(cert.content_base64)
pkcs12_gen_result = pkcs12_generator.generate('1234')
- Os samples alertam que a chave privada deve ser criptografada antes de ser guardada em um banco de dados.
- O sample em Python depois junta a chave e o certificado em um arquivo PKCS #12 com o PKI Express, para assinar com ele mais tarde. Para que o Amplia gere a chave e devolva o arquivo PKCS #12, veja Emitir um arquivo PKCS #12.
A chamada de emissão
POST /api/v2/certificates recebe um IssueCertificateRequest:
| Campo | Significado |
|---|---|
orderId | Id do pedido a atender. |
csr | O CSR. A demo de SSL/TLS o envia codificado em PEM. |
keyMedia | Onde a chave fica; veja Mídia da chave. |
keyId | Id de uma chave. |
TODO(docs): a que se refere keyId.
A resposta é um CertificateModel2 com o id do certificado, o content dele (em Base64), datas, número de série e, em info, o
subject, o emissor, os pontos de distribuição de LCR e as URIs de OCSP. POST /api/certificates recebe o mesmo corpo e devolve o
CertificateModel mais antigo.
A demo de e-CNPJ envia este corpo, com o enum como número:
{
"OrderId": "00000000-0000-0000-0000-000000000000",
"Csr": "<Csr, 944 bytes>",
"KeyMedia": 1
}
Para ler o certificado depois, use GET /api/v2/certificates/{id} (com fillContent=true para incluir content) ou baixe-o de
GET /api/certificates/{id}/content.
TODO(docs): o formato do arquivo devolvido por GET /api/certificates/{id}/content.
Mídia da chave
keyMedia é PC, CryptoDevice, Mobile ou Cloud.
- Uma chave gerada no seu servidor, ou pelo Web PKI no navegador do usuário, no computador dele:
PC. - Uma chave gerada pelo Web PKI em um token ou smart card:
CryptoDevice.
O keyMediaConstraints de um pedido lista as mídias da chave que ele aceita.
Só o cliente Node.js envia keyMedia: o enum KeyMedia dele vem de amplia-client/lib/enums, já que o ponto de entrada do pacote não o
exporta. O cliente Java envia o id do pedido, o CSR e, opcionalmente, keyId; os clientes PHP e Python enviam só o id do pedido e o CSR.
TODO(docs): que mídia da chave o Amplia registra quando a requisição não traz nenhuma.
TODO(docs): quando usar Mobile e Cloud (o Amplia guarda ele mesmo as chaves dos certificados em nuvem, veja gerenciamento de certificados em nuvem).
Gerar a chave no navegador do usuário
Com o Web PKI, a chave pode ser gerada no computador ou no token do usuário pela sua própria página, e só o CSR
chega ao seu servidor. O Web PKI devolve o id da chave junto com o CSR: depois da emissão, passe o id de volta para
importCertificate (ou
importTokenCertificate)
para instalar o certificado junto da chave.
O par de chaves em si vem de
generateSoftwareRsaKeyPair
ou de generateTokenRsaKeyPair.
TODO(docs): nenhum artigo ou sample mostra a geração de chave do Web PKI junto com o Amplia; para que a própria página do Amplia faça isso, veja Emitir na máquina do titular.
Certificados SSL/TLS
A demo de SSL/TLS gera uma chave RSA de 2048 bits e um CSR no servidor dela, cria um pedido SSL e emite o
certificado com a mídia da chave PC; os visitantes também podem trazer o próprio CSR.
- Ela verifica o CSR do usuário antes de chamar o Amplia: no máximo 16 KB, em PEM, Base64 ou DER, uma chave RSA de 2048 a 4096 bits ou uma chave EC em P-256 ou P-384, e uma assinatura que confere. Ela envia ao Amplia a requisição recodificada em PEM.
- O que ela devolve depende de quem gerou a chave: com uma chave do servidor, um .pfx, a chave privada em PEM e um .crt com o certificado e a AC emissora, nunca a raiz; com o CSR do usuário, só o .crt. Ela mantém as chaves só em memória.
Emitir um e-CPF depois de uma verificação facial
A demo de e-CPF com o rosto verifica a identidade do titular antes da emissão: o Datavalid do Serpro compara o rosto dele com a foto da CNH, pelo Lacuna Bio no Rest PKI Core. Depois que o rosto é aprovado, ela emite o e-CPF a partir de um CSR, como no fluxo desta página, sem a página de emissão do Amplia e sem retorno. Para a captura do rosto, veja o cadastro biométrico e a autenticação facial do Rest PKI Core.
- A demo faz a verificação
pf-basicado Datavalid antes de qualquer captura do rosto: o nome precisa conferir exatamente, a data de nascimento conferir, o CPF estar regular e existir uma CNH. - Ela cadastra o rosto com os dígitos do CPF como identificador do titular (subject identifier) e
VerifyFaceIdentityExternally = true; comBioSubjectAlreadyEnrolled, ela inicia uma autenticação facial em vez disso. - O resultado do Datavalid não vem no status de conclusão: a demo o lê com
GetSessionDetailsAsync(sessionId), que exige uma chave de API com permissão para ver sessões biométricas.
TODO(docs): nenhuma sequência de chamadas foi gravada para essa demo, e nenhum artigo cobre a verificação do Datavalid.