OpenSSL VPN Serveurs de messagerie |
OpenSSL/Rsa-cryptoapi-opensslLes structures de stockage de Microsoft ont la particularité de ne pas être chiffrées et d'être au format little-endian contrairement à OpenSSL qui travaille en big-endian. Le résultat est que toutes les structures doivent être inversées lors du passage d'un monde à l'autre, heureusement depuis la version 0.9.8h des options non documentées ont été ajoutées aux commandes OpenSSL pour faciliter l'interopérabilité. Quelques exemples d'utilisation des librairies CryptoAPI création d'une clé asymétrique // longueur de la clé 1024 = 1024 << 16 #define KEYLENGTH 0x04000000 void dump(TCHAR *dest,BYTE* pBuffer,DWORD& dwSize) { FILE* file; file = _tfopen(dest,TEXT("wb")); fwrite(pBuffer,sizeof(BYTE),dwSize,file); fclose(file); } int cipherdecipher() { DWORD dwFlags = 0; HCRYPTPROV hProv=NULL; HCRYPTKEY hPrivateKey; BYTE* pbPublicKeyBlob=NULL,*pbPrivateKeyBlob=NULL; DWORD dwPublicKeyBlobLen=0,dwPrivateKeyBlobLen=0; DWORD dwBlockLen=0,dwBlockSize=0; DWORD dwDataLen; BYTE *pbBuffer; DWORD dwBufferSize; CryptAcquireContext(&hProv, NULL, MS_ENHANCED_PROV, PROV_RSA_FULL, dwFlags); // create RSA keys CryptGenKey(hProv, CALG_RSA_KEYX, KEYLENGTH | CRYPT_EXPORTABLE, &hPrivateKey); //export public key CryptExportKey(hPrivateKey, NULL, PUBLICKEYBLOB, 0, NULL, &dwPublicKeyBlobLen); pbPublicKeyBlob = (BYTE*) malloc(dwPublicKeyBlobLen); CryptExportKey(hPrivateKey, NULL, PUBLICKEYBLOB, 0, pbPublicKeyBlob, &dwPublicKeyBlobLen); dump(_T("c:\\tmp\\pub.rsa"),pbPublicKeyBlob,dwPublicKeyBlobLen); //export private key CryptExportKey(hPrivateKey, NULL, PRIVATEKEYBLOB, 0, NULL, &dwPrivateKeyBlobLen); pbPrivateKeyBlob = (BYTE*) malloc(dwPrivateKeyBlobLen); CryptExportKey(hPrivateKey, NULL, PRIVATEKEYBLOB, 0, pbPrivateKeyBlob, &dwPrivateKeyBlobLen); dump(_T("c:\\tmp\\priv.rsa"),pbPrivateKeyBlob,dwPrivateKeyBlobLen); // get the cipher block length dwDataLen=sizeof(dwBlockLen); CryptGetKeyParam(hPrivateKey, KP_BLOCKLEN, (LPBYTE)&dwBlockLen,&dwDataLen,0); dwBlockSize = dwBlockLen/8; pbBuffer = (BYTE*) malloc(dwBlockSize); dwBufferSize = dwBlockSize-11; //padding PKCS #1 v1.5 for(UINT i =0; i<dwBufferSize; i++){pbBuffer[i] = i+32;} CryptEncrypt(hPrivateKey, NULL, FALSE, 0, pbBuffer, &dwBufferSize, dwBlockSize); dump(_T("c:\\tmp\\cipher.bin"),pbBuffer,dwBufferSize); CryptDecrypt(hPrivateKey, NULL, FALSE, 0, (BYTE *)pbBuffer, &dwBufferSize); free(pbBuffer); free(pbPrivateKeyBlob); free(pbPublicKeyBlob); CryptDestroyKey(hPrivateKey); CryptReleaseContext(hProv,0); return 0; } Trois fichiers ont été créés: pub.rsa, priv.rsa et cipher.bin. La clef privée est capable de coder/décoder. Les fichiers devront être transformés en base64 pour être réintroduits dans les codes par la commande ci-dessous
chiffrement avec la clé publique int simplecipher() { TCHAR szPub[]=_T("BgIAAACkAABSU0ExAAQAAAEAAQCxDs+RugWaFnQVMdZhirCBxQ5b2bpJtk24B6nediR933O2x9GynHDJ/WUPDn\ BuPcsw1JCZhsb0P2QUs9KU+iV2P7rJn2dREEjOJ82bN/Y6t4mp65JrOXdFhgtJPG9YbRcOQKNftnqr/OrwxjQcok9T63vaTgR+7JXuir3KFB5PrA=="); DWORD dwFlags = 0; HCRYPTPROV hProv=NULL; HCRYPTKEY hPublicKey; DWORD dwPubKeySize=0; BYTE* pbPubKey; DWORD dwBlockLen=0,dwDataLen=0; BYTE *pbBuffer; DWORD dwBufferSize; DWORD dwBlockSize=0; CryptStringToBinary(szPub,0,CRYPT_STRING_BASE64,NULL,&dwPubKeySize,0,0); pbPubKey = (BYTE*)malloc(dwPubKeySize); CryptStringToBinary(szPub,0,CRYPT_STRING_BASE64,pbPubKey,&dwPubKeySize,0,0); CryptAcquireContext(&hProv, NULL, MS_ENHANCED_PROV, PROV_RSA_FULL, dwFlags); CryptImportKey(hProv,pbPubKey,dwPubKeySize,0,CRYPT_EXPORTABLE,&hPublicKey); dwDataLen=sizeof(dwBlockLen); CryptGetKeyParam(hPublicKey, KP_BLOCKLEN, (LPBYTE)&dwBlockLen,&dwDataLen,0); dwBlockSize = dwBlockLen/8; pbBuffer = (BYTE*) malloc(dwBlockSize); dwBufferSize = dwBlockSize-11; //padding PKCS #1 v1.5 for(UINT i =0; i<dwBufferSize; i++){pbBuffer[i] = i+32;} CryptEncrypt(hPublicKey, NULL, FALSE, 0, pbBuffer, &dwBufferSize, dwBlockSize); dump(_T("c:\\tmp\\cipher.bin"),pbBuffer,dwBufferSize); free(pbPubKey); free(pbBuffer); CryptDestroyKey(hPublicKey); CryptReleaseContext(hProv,0); return 0; } déchiffrement avec la clef privée int simpledecipher() { TCHAR szPriv[]=_T("BwIAAACkAABSU0EyAAQAAAEAAQB3yEczW8w8N5/YC5cfOrhGAxRAmCl1uN0BzTei\ CAXuCQNjY2LEhx1Vits2GeSVqtn7m774ta2+3WnIHhZByJjH4a5ad2KYqZOVAne/\ jhKByD3XApgT1ocACdb6md3Whbf7n5miUFsHVVY8wqVIh1HpDR3tnhtSoTYMVJFg\ A7ILx4Hr8XQC2t7q6uD3UY0622kmqR3jQ0kmOvek6qWr0o9sB+aPbisjUh4RKdMC\ w+4JWvgF9Vbnk9HlH7lHuMxJyP73D5FNRmmjLMFNQ4Dk23gS8h4C0x0x0AeK6USZ\ ZG/EXiWTFy8Jvwb/sdgzBngiw+GHa+SgnixtVl0DMDBnN//HAcYXWHGVmCwaQEFY\ PoARWH1PVfZQ8/pCdHb1ju8O/5jTETtBuj3b3J1aP2QxL07zmsi//RWXXmLnd0d8\ aIQhKdeOOibcvSLKCZcvOrv+SSSaZPhSQZ2uYYCENu93gLm5q57j3iuzxwUagKXA\ HRIcBU0LR3kw52V89YG+To2TFlq77KYZS98otYMqEYy+1dyL3mWLK7Y3X61Op9pU\ 1hdaVOLMgNhvYmoV71oHUIF368lOHR7LUNu2vufyGClFcQpZAQJW5+VGQ8iJfBfQ\ NA8LDhlcCO30LkGriG4lmHkHj6gxjFhRwsZA3h/HvWAZDUYX3+syF+m8KQ1ZWEwo\ KhGbvFu486whDGAbHSQ2fHmZbAN3kPodkl/DMrqEFiXePpjzRC2aYRpKFfWK/tVQ\ Yvs0eGZOd/U0epXgMJp7NOyhHzQ="); TCHAR szCipher[]=_T("GV5v/edRWPFxuK0vG8UP0/vZ2m8U62xrvJLHLnuMuxbs6RumLqspT2dnU38HXjWSRaAH/EWoUWwkdMyUq3/fAsmO+vef6Xf0yUcg50Vy2wFkZdWpw3+htJ3eJaOo8nV1aXyRghR38C7/fRoDfmReIHH/cB+Udx7AgEY4LMCZiWM="); HCRYPTPROV hProv=NULL; HCRYPTKEY hPrivateKey; DWORD dwPrivateKeySize; BYTE *pbPrivateKey; DWORD dwCipherSize; BYTE* pbCipher; DWORD dwFlags=0; CryptStringToBinary(szPriv,0,CRYPT_STRING_BASE64,NULL,&dwPrivateKeySize,0,0); pbPrivateKey = (BYTE*)malloc(dwPrivateKeySize); CryptStringToBinary(szPriv,0,CRYPT_STRING_BASE64,pbPrivateKey,&dwPrivateKeySize,0,0); CryptStringToBinary(szCipher,0,CRYPT_STRING_BASE64,NULL,&dwCipherSize,0,0); pbCipher = (BYTE*)malloc(dwCipherSize); CryptStringToBinary(szCipher,0,CRYPT_STRING_BASE64,pbCipher,&dwCipherSize,0,0); CryptAcquireContext(&hProv, NULL, MS_ENHANCED_PROV, PROV_RSA_FULL, dwFlags); CryptImportKey(hProv,pbPrivateKey,dwPrivateKeySize,0,CRYPT_EXPORTABLE,&hPrivateKey); CryptDecrypt(hPrivateKey, NULL, FALSE, 0, (BYTE *)pbCipher, &dwCipherSize); return 0; } Comme dit plus haut, OpenSSL est capable d'interpréter nativement les structures spécifiques de Microsoft grâce à un nouveau format de certificat le MS, n'oublions pas non plus d'inverser le flux chiffré par la commande -rev et voici le résultat:
|