4

我正在为我的 Azure 项目使用加密技术,但我遇到了 RsaKey 问题。当用户注册应用程序时,会创建一个 RsaKey 并将其关联到用户。这是代码:

   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);

在此之后,我必须使 RsaKey 持久化,然后将其存储在用户容器中的专用 blob 中。由于 RsaKey 不可序列化,因此我对 Json 字符串使用了一点“技巧”。这里的代码:

 string jsonString = Newtonsoft.Json.JsonConvert.SerializeObject(key);

                    using (var stream = new MemoryStream(Encoding.Default.GetBytes(jsonString), false))
                    {             
                        blob.UploadFileToBlob(item.PartitionKey, "key", stream); // this method creates a blob called "key" in the container named [item.PartitionKey] and stores the stream   
                    }

注册后,我当然需要使用 RsaKey 来执行一些操作,比如访问一些隐藏字段,访问其他 blob 中的一些特殊文件等。我在这种情况下所做的代码如下所示:

 User user = GetUser();

            Resolver res = new Resolver();
            res.Add(user.PartitionKey);

            TableRequestOptions retrieveOptions = new TableRequestOptions()
            {
                EncryptionPolicy = new TableEncryptionPolicy(null, res)
            };

            // Retrieve Entity
            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"); // this method goes to the blob "key" in the container named [container] and download the content of the blob using a MemoryStream
            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)。因此,我尝试使用我存储的同一个 Kid 创建一个新的 RsaKey ( 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: 
4

0 回答 0