So I’ve run into an interesting issue when trying to use the new cryptography namespace in WinRT (Windows::Security::Cryptography). Namely, when I try to use the CryptographicEngine::Encrypt() or CryptographicEngine::Decrypt() methods, they throw an InvalidArgumentException. I’m by no means a pro in this area, but I feel I’ve narrowed it down to a fairly basic scenario and am still getting the failure:
//------------------------------------------------------------------------------
// TestEncryptDecrypt
// Simple test that encrypts a string, then decrypts it and compares the result.
void TestEncryptDecrypt()
{
// Select asymmetric algorithm
Platform::String^ strAlgorithm = Windows::Security::Cryptography::Core::AsymmetricAlgorithmNames::RsaOaepSha512;
Windows::Security::Cryptography::Core::AsymmetricKeyAlgorithmProvider^ spAlgorithm = Windows::Security::Cryptography::Core::AsymmetricKeyAlgorithmProvider::OpenAlgorithm(strAlgorithm);
// Create public/private keys
unsigned int nKeySize = 512;
Windows::Security::Cryptography::Core::CryptographicKey^ spKeyPair = spAlgorithm->CreateKeyPair(nKeySize);
// Message to encrypt/decrypt
Platform::String^ strMessage = L"Test Message";
Windows::Storage::Streams::IBuffer^ spMessageBuffer = Windows::Security::Cryptography::CryptographicBuffer::ConvertStringToBinary(strMessage, Windows::Security::Cryptography::BinaryStringEncoding::Utf8);
// Encrypt the data
// *** InvalidArgumentException throw here ***
Windows::Storage::Streams::IBuffer^ spEncryptedBuffer = Windows::Security::Cryptography::Core::CryptographicEngine::Encrypt(spKeyPair, spMessageBuffer, nullptr /*Initialization vector not used with asymmetric algorithms.*/);
// Decrypt the data
Windows::Storage::Streams::IBuffer^ spUnencryptedBuffer = Windows::Security::Cryptography::Core::CryptographicEngine::Decrypt(spKeyPair, spEncryptedBuffer, nullptr /*Initialization vector not used with asymmetric algorithms.*/);
// Retrieve the original message
Platform::String^ strUnencryptedMessage = Windows::Security::Cryptography::CryptographicBuffer::ConvertBinaryToString(Windows::Security::Cryptography::BinaryStringEncoding::Utf8, spUnencryptedBuffer);
Assert(strUnencryptedMessage == strMessage);
}
I could still be doing something silly (and probably am), but unfortunately I’m not seeing it… any ideas?
Thanks in advance! 🙂
And as usual I stumble upon the answer about half an hour after posting… 🙂
It turns out that the key size I was using is not supported by RSA_OAEP_SHA512. You need to use a larger key (I’d actually tried 1024 originally before switching to 512, but is seems that is too small as well). Using a key size of 2048 or 4096 works fine though.
Anyway, I figured this out by playing with the WinRT Crypto sample which can be found at http://code.msdn.microsoft.com/windowsapps/CryptoWinRT-54ff3d9f. It throws the exception also, but has some error handling code nearby that indicates what happened after catching the rather useless exception. The sample is very well written, so I’d recommend checking it out if you’re having a similar problem.
On a separate note, I do find it slightly annoying that the exception isn’t thrown when creating the key, as getting an InvalidArgumentException is cryptic enough without having it thrown in a funny spot. And it seems like it would have been possible to throw it during key creation as the algorithm has already been selected at this point.
Anyway, problem solved, and hopefully this post will help someone else out!