Microsoft ECSP를 사용하여 RSA 공개 키만으로 작은 데이터 블록을 암호화하는 방법은 무엇입니까?

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

  •  08-07-2019
  •  | 
  •  

문제

512 비트 RSA 공개 키를 사용하여 작은 데이터 블록 (16 바이트)을 암호화해야합니다. 문서화 cryptencrypt 기능은 다음을 나타냅니다

Microsoft Enhanced Cryptographic Provider는 RSA 공개 키와 RSA 개인 키를 사용한 해독을 지원하는 직접 암호화를 지원합니다. 암호화는 PKCS #1 패딩을 사용합니다.

그래도 나에게 효과가 없었습니다. 글쎄, 내 코드는 작동하고 올바른 크기의 암호화 된 데이터 블록을 생성하지만 OpenSSL은 디 시퍼에 실패합니다. cryptencrypt가 여전히 대칭 사이퍼를 사용하는 것처럼 보입니다.

불행히도 내가 찾은 모든 예제는 대칭 사이퍼와 결합 된 암호화를 참조하므로 손에 대한 예제가 없습니다.

누구든지 저를 그러한 모범을 가리키거나 내가 놓친 명백한 함정이 없는지 알려줄 수 있습니까?

고맙습니다.

도움이 되었습니까?

해결책

이것은 an처럼 들립니다 엔지니어 문제. 마이크로 소프트 cryptencrypt 함수는 암호 텍스트를 Little-Endian 형식으로 반환하는 반면 OpenSSL은 데이터가 큰 엔디안 형식으로 예상됩니다. OpenSSL로 전달하기 전에 암호화 된 데이터를 뒤집어 야합니다.

다른 팁

코드는 다음과 같습니다 (누군가 가이 주제를 구글을 뽑은 경우를 대비하여) :

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
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top