void CryptoProxy::encrypt(CryptoKey* key, const ByteVector& data, ByteVector& encryptedData) { if ((data.length() % 16) > 0) throw runtime_error("encrypt: incorrect data length"); encryptedData = data; //Crypto encrypts in-place // NOTE: do not reserve block for padding, specify final = FALSE instead //encryptedData.append(0x00, 16); // add one extra block as MS wants it for padding const DWORD bytesToEncrypt = static_cast<DWORD>(data.size()); DWORD dataSize = bytesToEncrypt; try { TOE(CryptEncrypt(*key, 0, FALSE/*final*/, 0/*flags*/, &encryptedData.front(), &dataSize, static_cast<DWORD>(encryptedData.size())), "CryptEncrypt 1st"); } catch (WinApiError& e) { // larger buffer is required?? if (e.getErr() == ERROR_MORE_DATA) { encryptedData.append(0x00, dataSize - encryptedData.size()); // try again, no second catch this time dataSize = bytesToEncrypt; //set again to input data length TOE(CryptEncrypt(*key, 0, FALSE/*final*/, 0/*flags*/, &encryptedData.front(), &dataSize, static_cast<DWORD>(encryptedData.size())), "CryptEncrypt 2nd"); } else throw; // another error -> re-throw } // strip the padding encryptedData.resize(bytesToEncrypt); }
void CryptoHash::getValue(ByteVector& value) { DWORD reqHashLen = 0; TOE(CryptGetHashParam(handle, HP_HASHVAL, NULL, &reqHashLen, 0), "CryptGetHashParam"); value.resize(reqHashLen); TOE(CryptGetHashParam(handle, HP_HASHVAL, &value.front(), &reqHashLen, 0), "CryptGetHashParam"); }
void CryptoProxy::decrypt(CryptoKey* key, const ByteVector& data, ByteVector& decryptedData) { decryptedData = data; //Crypto decrypts in-place DWORD dataSize = static_cast<DWORD>(data.size()); // NOTE: check FINAL again - currently no FINAL to avoid checking padding //TOE(CryptDecrypt(*key, 0, TRUE, 0/*flags*/, &decryptedData.front(), &dataSize), "CryptDecrypt"); TOE(CryptDecrypt(*key, 0, FALSE, 0/*flags*/, &decryptedData.front(), &dataSize), "CryptDecrypt"); if (dataSize < decryptedData.size()) { decryptedData.resize(decryptedData.size() - dataSize); } }
void CryptoProxy::genRand(unsigned int reqSize, ByteVector& randData) { randData.resize(reqSize); TOE(CryptGenRandom(impl->provider, reqSize, &randData.front()), "CryptGenRandom"); }