I use cryptography for my Azure project and I have problems with RsaKey. When a user subscribes to an application, RsaKey is created and attached to the user. This is the code:
string storageConnectionString = CloudConfigurationManager.GetSetting("StorageConnectionString");
CloudStorageAccount storageAccount;
try
{
storageAccount = CloudStorageAccount.Parse(storageConnectionString);
}
catch (FormatException)
{
Console.WriteLine("Invalid storage account information provided. Please confirm the AccountName and AccountKey are valid in the app.config file - then restart the sample.");
Console.WriteLine("Press any key to exit");
Console.ReadLine();
throw;
}
catch (ArgumentException)
{
Console.WriteLine("Invalid storage account information provided. Please confirm the AccountName and AccountKey are valid in the app.config file - then restart the sample.");
Console.WriteLine("Press any key to exit");
Console.ReadLine();
throw;
}
CloudTableClient client = storageAccount.CreateCloudTableClient();
CloudTable table = client.GetTableReference(tableName);
RsaKey key = new RsaKey(item.PartitionKey);
TableRequestOptions insertOptions = new TableRequestOptions()
{
EncryptionPolicy = new TableEncryptionPolicy(key, null)
};
table.Execute(TableOperation.Insert(item), insertOptions, null);
After that I have to make RsaKey permanent, then I store it in a dedicated blob in the user container. Since RsaKey is not Serializable, I use a little "trick" with a Json string. Here is the code:
string jsonString = Newtonsoft.Json.JsonConvert.SerializeObject(key);
using (var stream = new MemoryStream(Encoding.Default.GetBytes(jsonString), false))
{
blob.UploadFileToBlob(item.PartitionKey, "key", stream);
}
After registration, of course, I need to use RsaKey to perform some operations, for example, have access to some hidden fields, have access to some special files in other blocks, etc. What I do in this case is shown in this code
User user = GetUser();
Resolver res = new Resolver();
res.Add(user.PartitionKey);
TableRequestOptions retrieveOptions = new TableRequestOptions()
{
EncryptionPolicy = new TableEncryptionPolicy(null, res)
};
string storageConnectionString = CloudConfigurationManager.GetSetting("StorageConnectionString");
CloudStorageAccount storageAccount;
try
{
storageAccount = CloudStorageAccount.Parse(storageConnectionString);
}
catch (FormatException)
{
Console.WriteLine("Invalid storage account information provided. Please confirm the AccountName and AccountKey are valid in the app.config file - then restart the sample.");
Console.WriteLine("Press any key to exit");
Console.ReadLine();
throw;
}
catch (ArgumentException)
{
Console.WriteLine("Invalid storage account information provided. Please confirm the AccountName and AccountKey are valid in the app.config file - then restart the sample.");
Console.WriteLine("Press any key to exit");
Console.ReadLine();
throw;
}
CloudTableClient client = storageAccount.CreateCloudTableClient();
CloudTable table = client.GetTableReference("user");
TableOperation operation = TableOperation.Retrieve(user.PartitionKey, user.RowKey);
TableResult result;
try
{
result = table.Execute(operation, retrieveOptions, null);
}
catch (Exception e) { }
Resolver - , IKeyResolver, ResolveKeyAsync . :
public class Resolver: IKeyResolver
{
TableUtility table;
BlobUtility blob;
string container;
public Resolver()
{
table = new TableUtility();
blob = new BlobUtility();
}
public void Add(string container){
this.container= container;
}
public async Task<IKey> ResolveKeyAsync(string kid, CancellationToken token)
{
IKey result;
string jsonString = blob.BlobToText(container, "key");
var javaScriptSerializer = new System.Web.Script.Serialization.JavaScriptSerializer();
result = Newtonsoft.Json.JsonConvert.DeserializeObject<RsaKey>(jsonString);
return await Task.FromResult(result);
}
}
, RsaKey . , jsonString , "Kid" result , , (, , Kid). , RsaKey Kid, (RsaKey key = new RsaKey(partitionKey)), (TableResult result null). ? , ?
table.Execute(operation, retrieveOptions, null); try/catch ( RsaKey, RsaKey key = new RsaKey(partitionKey)), :
Microsoft.WindowsAzure.Storage.StorageException was caught
_HResult=-2146233088
_message=Decryption logic threw error. Please check the inner exception for more details.
HResult=-2146233088
IsTransient=false
Message=Decryption logic threw error. Please check the inner exception for more details.
Source=Microsoft.WindowsAzure.Storage
IsRetryable=false
StackTrace:
in Microsoft.WindowsAzure.Storage.Core.Executor.Executor.ExecuteSync[T](RESTCommand`1 cmd, IRetryPolicy policy, OperationContext operationContext) in c:\Program Files (x86)\Jenkins\workspace\release_dotnet_master\Lib\ClassLibraryCommon\Core\Executor\Executor.cs:line 820
in Microsoft.WindowsAzure.Storage.Table.TableOperation.Execute(CloudTableClient client, CloudTable table, TableRequestOptions requestOptions, OperationContext operationContext) in c:\Program Files (x86)\Jenkins\workspace\release_dotnet_master\Lib\ClassLibraryCommon\Table\TableOperation.cs:line 41
in Microsoft.WindowsAzure.Storage.Table.CloudTable.Execute(TableOperation operation, TableRequestOptions requestOptions, OperationContext operationContext) in c:\Program Files (x86)\Jenkins\workspace\release_dotnet_master\Lib\ClassLibraryCommon\Table\CloudTable.cs:line 53
in WebRole.Controllers.AccountController.IsProfileCompleted() in c:\Users\HP\Source\Repos\scalablepredictor\WebRole\Controllers\AccountController.cs:line 343
InnerException: System.AggregateException
_HResult=-2146233088
_message=One or more errors occured.
HResult=-2146233088
IsTransient=false
Message=One or more errors occured.
Source=mscorlib
StackTrace:
in System.Threading.Tasks.Task`1.GetResultCore(Boolean waitCompletionNotification)
in Microsoft.WindowsAzure.Storage.Table.TableEncryptionPolicy.DecryptMetadataAndReturnCEK(String partitionKey, String rowKey, EntityProperty encryptionKeyProperty, EntityProperty propertyDetailsProperty, EncryptionData& encryptionData) in c:\Program Files (x86)\Jenkins\workspace\release_dotnet_master\Lib\ClassLibraryCommon\Table\TableEncryptionPolicy.cs:line 205
InnerException: System.Security.Cryptography.CryptographicException
_HResult=-2146233296
_message=Error occurred while decoding OAEP padding.
HResult=-2146233296
IsTransient=false
Message=Error occurred while decoding OAEP padding.
Source=mscorlib
StackTrace:
in System.Security.Cryptography.RSACryptoServiceProvider.DecryptKey(SafeKeyHandle pKeyContext, Byte[] pbEncryptedKey, Int32 cbEncryptedKey, Boolean fOAEP, ObjectHandleOnStack ohRetDecryptedKey)
in System.Security.Cryptography.RSACryptoServiceProvider.Decrypt(Byte[] rgb, Boolean fOAEP)
in Microsoft.Azure.KeyVault.Cryptography.Algorithms.RsaOaep.RsaOaepDecryptor.TransformFinalBlock(Byte[] inputBuffer, Int32 inputOffset, Int32 inputCount)
in Microsoft.Azure.KeyVault.RsaKey.<UnwrapKeyAsync>d__6.MoveNext()
InnerException: