dgorti
dgorti

Reputation: 1240

Windows Store App Decrypt using a private key

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.

  1. If I have a base64 encrypted string, a) How do I load the key from the base64 encoded private key string

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

  1. The base64 string of private key seems to be longer than the public key. I wonder why that is. Shouldn't the key length be same for both public and private key? In any case this does not bother me but I am curious

Upvotes: 2

Views: 658

Answers (1)

dgorti
dgorti

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

Related Questions