2008-11-17 3 views
2

512 비트 RSA 공용 키를 사용하여 작은 데이터 블록 (16 바이트)을 암호화해야합니다. MS CSP API를 제외하고는 대부분의 암호화 라이브러리에 대해 상당히 쉬운 작업입니다. CryptEncrypt 기능 문서는Microsoft ECSP를 사용하여 RSA 공개 키로만 작은 데이터 블록을 암호화하는 방법은 무엇입니까?

마이크로 소프트 향상된 암호화 공급자는 RSA 개인 키와 RSA 공개 키 및 암호 해독과 직접 암호화를 지원한다고. 암호화는 PKCS # 1 패딩을 사용합니다.

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

불행히도 내가 발견 한 모든 예제는 대칭형 암호화기와 결합 된 암호화를 의미하므로 모든 것을 명확하게 만드는 손쉬운 예제가 없습니다.

누군가가 저에게 그런 예를 지적 해 주거나 제가 놓친 분명한 함정이 없는지 알려주시겠습니까?

감사합니다.

답변

8

이 메시지는 endianness 호와 같습니다. Microsoft의 CryptEncrypt 함수는 암호문을 리틀 엔디안 형식으로 반환하지만 OpenSSL은 해당 데이터가 빅 엔디안 형식이어야합니다. 암호화 된 데이터를 OpenSSL에 전달하기 전에이를 역전해야합니다.

+0

빙고. 지적 해 주셔서 고맙습니다. 함정은 너무 분명했습니다. :) –

7

여기 (단지의 경우 누군가에이 주제를 봤있다) 코드입니다 :

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, "", 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