Reputation: 1240
I have an app that creates a keypair and sends the public key to a device. The device then encrypts some info and I need to decrypt using my private key. I generated a key pair String AsymmetricAlgName = Windows.Security.Cryptography.Core.AsymmetricAlgorithmNames.RsaPkcs1;
AsymmetricKeyAlgorithmProvider asym =
AsymmetricKeyAlgorithmProvider.OpenAlgorithm(AsymmetricAlgName);
CryptographicKey keyPair = asym.CreateKeyPair(2048);
I exported the public key using
IBuffer buffPublicKey = keyPair.ExportPublicKey();
byte[] pubPublickeyBytes;
CryptographicBuffer.CopyToByteArray(buffPublicKey, out pubPublickeyBytes);
string pubKeyStr = Convert.ToBase64String(pubPublickeyBytes);
so far so good.
My app stores the private key generated in a base64 string
IBuffer buffPrivateKeyRsa = keyPair.Export(CryptographicPrivateKeyBlobType.Pkcs1RsaPrivateKey);
CryptographicBuffer.CopyToByteArray(buffPrivateKeyRsa, out pubPrivateBytesRsa);
string priKeyStrRsa = Convert.ToBase64String(pubPrivateBytesRsa);
I have 2 questions.
b) How do I decrypt? It is all in the windows store app, so I am not transporting the private key elsewhere. I looked at the decrypt method but it needs a cryptographic key and I am not sure how I would construct that from a base64 encoded string
Upvotes: 2
Views: 658
Reputation: 1240
After several hours, I figured it out.
First, it is expected that the private key base 64 string is longer than the public key in base64.
Second, the APIs are a little interesting (unintuitive). To import a private key only, you still need to import a key par. There is import public key method but there is no import private key method.
CryptographicKey privKey = asym.ImportKeyPair(CryptographicBuffer.DecodeFromBase64String(priKeyStrRsa), CryptographicPrivateKeyBlobType.Pkcs1RsaPrivateKey);
IBuffer decryptedBuffer = CryptographicEngine.Decrypt(privKey, encryptedBuffer, null);
byte[] decrptedBytes;
CryptographicBuffer.CopyToByteArray(decryptedBuffer, out decrptedBytes);
string data = Encoding.UTF8.GetString(decrptedBytes, 0, decrptedBytes.Length);
So first you import a private key you stored somewhere and you would have encrypted the data like so
string unencData = "some data";
IBuffer unencCryptBuffer = CryptographicBuffer.CreateFromByteArray(Encoding.UTF8.GetBytes(unencData));
IBuffer publicKeyBuffer = CryptographicBuffer.DecodeFromBase64String(pubKeyStr);
CryptographicKey pubKey = asym.ImportPublicKey(publicKeyBuffer);
IBuffer encryptedBuffer = CryptographicEngine.Encrypt(pubKey, unencCryptBuffer, null);
Third, the thing that took most time for me to figure out is that the party I am talking to, a hardware device, is using OAEP padding. SO my decrypt is failing. Thr trick here is to use RsaOeapSha1 algorithm.
The complete sample is posted here
String AsymmetricAlgName = Windows.Security.Cryptography.Core.AsymmetricAlgorithmNames.RsaOaepSha1;
AsymmetricKeyAlgorithmProvider asym = AsymmetricKeyAlgorithmProvider.OpenAlgorithm(AsymmetricAlgName);
CryptographicKey keyPair = asym.CreateKeyPair(2048);
IBuffer buffPublicKey = keyPair.ExportPublicKey();
IBuffer buffPrivateKeyRsa = keyPair.Export(CryptographicPrivateKeyBlobType.Pkcs1RsaPrivateKey);
byte[] pubPublickeyBytes;
byte[] pubPrivateBytesRsa;
CryptographicBuffer.CopyToByteArray(buffPublicKey, out pubPublickeyBytes);
CryptographicBuffer.CopyToByteArray(buffPrivateKeyRsa, out pubPrivateBytesRsa);
string pubKeyStr = Convert.ToBase64String(pubPublickeyBytes);
string priKeyStrRsa = Convert.ToBase64String(pubPrivateBytesRsa);
string unencData = "some data";
IBuffer unencCryptBuffer = CryptographicBuffer.CreateFromByteArray(Encoding.UTF8.GetBytes(unencData));
IBuffer publicKeyBuffer = CryptographicBuffer.DecodeFromBase64String(pubKeyStr);
CryptographicKey pubKey = asym.ImportPublicKey(publicKeyBuffer);
IBuffer encryptedBuffer = CryptographicEngine.Encrypt(pubKey, unencCryptBuffer, null);
CryptographicKey privKey = asym.ImportKeyPair(CryptographicBuffer.DecodeFromBase64String(priKeyStrRsa), CryptographicPrivateKeyBlobType.Pkcs1RsaPrivateKey);
IBuffer decryptedBuffer = CryptographicEngine.Decrypt(privKey, encryptedBuffer, null);
byte[] decrptedBytes;
CryptographicBuffer.CopyToByteArray(decryptedBuffer, out decrptedBytes);
string data = Encoding.UTF8.GetString(decrptedBytes, 0, decrptedBytes.Length);
Upvotes: 1