Como criptografar o pequeno bloco de dados com apenas a chave pública RSA usando o Microsoft ECSP?

StackOverflow https://stackoverflow.com/questions/295345

  •  08-07-2019
  •  | 
  •  

Pergunta

Preciso criptografar um pequeno bloco de dados (16 bytes) usando a chave pública RSA de 512 bits - uma tarefa fácil para a maioria das bibliotecas de criptografia conhecidas por mim, exceto pela API MS CSP, como parece. Documentação para Cryptencrypt A função declara isso

O provedor criptográfico aprimorado da Microsoft suporta criptografia direta com chaves públicas da RSA e descriptografia com chaves privadas da RSA. A criptografia usa PKCS #1 preenchimento.

Mas não funcionou para mim. Bem, meu código funciona e produz um bloco de dados criptografado com tamanho correto, mas o OpenSSL falha em decifrá -lo. Parece muito com o CryptoCrypt ainda usa cypher simétrico.

Infelizmente, todos os exemplos que encontrei referem -se à criptografia combinada com cifra simétrica, para que não tenha um exemplo de funcionamento nas mãos, o que definitivamente facilitaria as coisas.

Por favor, alguém me indica um exemplo assim ou me avise se não há algumas armadilhas óbvias que perdi?

Obrigada.

Foi útil?

Solução

Isso soa como um endianness questão. Microsoft's Cryptencrypt A função retorna o texto cifrado em formato Little-Endian, enquanto o OpenSSL espera que seus dados estejam em formato big-endian. Você precisará reverter os dados criptografados antes de passá -los para o OpenSSL.

Outras dicas

Aqui está o código (caso alguém tenha pesquisado este tópico no Google):

BYTE *spkiData = SPKI; // X.509 ASN.1 encoded SubjectPublicKeyInfo
DWORD dwSPKISize = SPKI_SIZE; // 94 bytes for RSA

DWORD dwBufSize = 0;
// Get buffer size for decoded spki structure
CryptDecodeObject(X509_ASN_ENCODING, X509_PUBLIC_KEY_INFO, spkiData, dwSPKISize, 0, NULL, &dwBufSize);
BYTE* decBuf = new BYTE[dwBufSize];
CryptDecodeObject( X509_ASN_ENCODING, X509_PUBLIC_KEY_INFO, spkiData, dwSPKISize, 0, decBuf, &dwBufSize);
// Now decode the RSA Public key itself
CERT_PUBLIC_KEY_INFO * spki = (CERT_PUBLIC_KEY_INFO *) decBuf;
// Get buffer size for decoded public key structure
CryptDecodeObject( X509_ASN_ENCODING, RSA_CSP_PUBLICKEYBLOB, spki->PublicKey.pbData, spki->PublicKey.cbData, 0, 0, &dwBufSize);
// Get the RSA public key blob
BYTE *blobBuf = new BYTE[dwBufSize];
CryptDecodeObject(X509_ASN_ENCODING, RSA_CSP_PUBLICKEYBLOB, spki->PublicKey.pbData, spki->PublicKey.cbData, 0, blobBuf, &dwBufSize);
// Acquire crypto provider context
HCRYPTPROV hCryptProv = NULL;
CryptAcquireContext(&hCryptProv, 0, MS_ENHANCED_PROV, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT);
// Import key
HCRYPTKEY key = NULL;
CryptImportKey(hCryptProv, blobBuf, dwBufSize, 0, 0, &key);
// Get the key size
DWORD dwKeySize;
DWORD dwParamSize = sizeof(DWORD);
CryptGetKeyParam(key, KP_KEYLEN, (BYTE*) &dwKeySize, &dwParamSize, 0);
// we need it in bytes for convenience
dwKeySize /= 8;
// Now the fun
// allocate a buffer of key size
BYTE *data = new BYTE[dwKeySize];
// Copy data need to be encrypted
// With PKCS#1 padding data length can not exceed keysize - 11 bytes
DWORD dataLen = 16;
memcpy(data, "0123456789012345", dataLen);
CryptEncrypt(key, 0, TRUE, 0, data, &dataLen, dwKeySize)
// now convert it to big endian (for the rest of the world)
for (int i = 0; i < (dwKeySize / 2); i++) {
    BYTE c = data[i];
    data[i] = data[dwKeySize - 1 - i];
    data[dwKeySize - 1 - i] = c;
}
// now data points to a dwKeySize length block of RSA PKCS#v1.5 encrypted data
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top