{"id":15420905,"url":"https://github.com/charleszipp/azure-durable-entities-encryption","last_synced_at":"2025-04-19T14:56:41.687Z","repository":{"id":70871621,"uuid":"263735136","full_name":"charleszipp/azure-durable-entities-encryption","owner":"charleszipp","description":"Demonstrates how application level encryption can be implemented for durable entities","archived":false,"fork":false,"pushed_at":"2020-05-18T13:46:41.000Z","size":24,"stargazers_count":6,"open_issues_count":1,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-02-23T23:41:20.532Z","etag":null,"topics":["azure-functions","azure-functions-v3","durable-entities","durable-functions"],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/charleszipp.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-05-13T20:23:16.000Z","updated_at":"2024-08-20T07:47:19.000Z","dependencies_parsed_at":"2023-08-19T23:00:59.768Z","dependency_job_id":null,"html_url":"https://github.com/charleszipp/azure-durable-entities-encryption","commit_stats":{"total_commits":12,"total_committers":2,"mean_commits":6.0,"dds":0.08333333333333337,"last_synced_commit":"bbfb8eae5758ddc06d45a45cddafaf00c8d1d6a7"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/charleszipp%2Fazure-durable-entities-encryption","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/charleszipp%2Fazure-durable-entities-encryption/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/charleszipp%2Fazure-durable-entities-encryption/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/charleszipp%2Fazure-durable-entities-encryption/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/charleszipp","download_url":"https://codeload.github.com/charleszipp/azure-durable-entities-encryption/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":241460054,"owners_count":19966511,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["azure-functions","azure-functions-v3","durable-entities","durable-functions"],"created_at":"2024-10-01T17:31:34.302Z","updated_at":"2025-04-19T14:56:41.680Z","avatar_url":"https://github.com/charleszipp.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Application Level Encryption for Azure Durable Entities\r\n\r\nThe code within this repository demonstrates a means by which durable entity state can be encrypted at the application layer. A key is configured for the function app. That key is then used during the serialization process to encrypt any properties annotated with the `Encrypted` attribute.\r\n\r\n## Dependencies\r\n\r\n- [.NET Core 3.1](https://dotnet.microsoft.com/download)\r\n- [Azure Storage Emulator](https://go.microsoft.com/fwlink/?linkid=717179\u0026clcid=0x409)\r\n- [Azure Storage Explorer](https://azure.microsoft.com/en-us/features/storage-explorer/)\r\n\r\n## Bootstrapping Encryption\r\n\r\nAs part of the `Configure` method in the `FunctionsStartup` class register the dependencies necessary to enable encryption\r\n\r\nRegister how to resolve the encryption options/configuration. The key is expected to come from a key management solution such as Azure Key Vault. See [Azure Key Vault Configuration Provider in ASP.NET Core](https://docs.microsoft.com/en-us/aspnet/core/security/key-vault-configuration?view=aspnetcore-3.1) for how to retrieve secrets from Azure Key Vault.\r\n\r\n```csharp\r\nbuilder.Services.AddSingleton(sp =\u003e new EncryptionOptions(config[\"ENCRYPTIONKey\"]));\r\n```\r\n\r\nRegister the implementation of `IEncryptionService` to be used\r\n\r\n```csharp\r\nbuilder.Services.AddSingleton\u003cIEncryptionService, EncryptionService\u003e();\r\n```\r\n\r\nRegister customization to `IMessageSerializerSettingsFactory` to customize how durable functions serializes the state\r\n\r\n```csharp\r\n//necessary to engage custom settings during serialization\r\nbuilder.Services.AddSingleton\u003cIContractResolver, EncryptedContractResolver\u003e();\r\nbuilder.Services.AddSingleton(sp =\u003e new JsonSerializerSettings { ContractResolver = sp.GetService\u003cIContractResolver\u003e() });\r\nbuilder.Services.AddSingleton\u003cIMessageSerializerSettingsFactory, SerializerSettingsFactory\u003e();\r\n```\r\n\r\nRegister customization to Json.NET's default serialization settings to customize how durable functions deserializes the state\r\n\r\n```csharp\r\n//necessary to engage custom settings during deserialization\r\nJsonConvert.DefaultSettings = () =\u003e builder.Services.BuildServiceProvider().GetService\u003cJsonSerializerSettings\u003e();\r\n```\r\n\r\n### Annotate Properties for Encryption\r\n\r\nTo indicate which entity properties should be encrypted, annotate the properties with the `Encrypted` attribute. The `EncryptedContractResolver` will scan for this attribute to determine which properties need to be encrypted/decrypted.\r\n\r\n```csharp\r\n[JsonObject(MemberSerialization = MemberSerialization.OptOut)]\r\npublic class AccountEntity : IAccountEntity\r\n{\r\n    // ensure account number is encrypted when saved\r\n    [Encrypted]\r\n    public string AccountNumber { get; set; }\r\n\r\n    public void Set(string accountNumber) =\u003e AccountNumber = accountNumber;\r\n\r\n    [FunctionName(nameof(AccountEntity))]\r\n    public static Task Run([EntityTrigger] IDurableEntityContext ctx) =\u003e ctx.DispatchAsync\u003cAccountEntity\u003e();\r\n}\r\n```\r\n\r\n### Testing The Encryption\r\n\r\nTo test the encryption/decryption in this sample, the following two endpoints can be used.\r\n\r\n#### PUT /accounts/{accountId}\r\n\r\nThis will set the account number to a value for the account of the provided `accountId`.\r\n\r\nThe value when saved to Azure Table Storage should be encrypted. The following is from the Hub Instances table; Input column for the row that represents the Durable Entity.\r\n\r\n```json\r\n{\"exists\":true,\"state\":\"{\\\"AccountNumber\\\":\\\"A1k9ufGmHFMgM83sE/8EdCMls/TLeXbWDEU32ZXrhE4=\\\"}\",\"sorter\":{}}\r\n```\r\n\r\n#### GET /accounts/{accountId}\r\n\r\nThis will retrieve the account entity for the account of the provided `accountId`.\r\n\r\nThe returned value should be decrypted\r\n\r\n```json\r\n{ \"accountNumber\": \"123ABC\" }\r\n```\r\n\r\n### Customize the Encryption\r\n\r\nTo customize the specific encryption algorithm used, a new implementation of `IEncryptionService` can be created. This will not change what properties are selected for encryption. It will only change how the properties annotated are encrypted \u0026 decrypted. If for example, something other than `AesManaged` is needed, a new implementation of IEncryptionService could be created to use a different cryptography implementation.\r\n\r\n```csharp\r\npublic interface IEncryptionService\r\n{\r\n    string Decrypt(string value);\r\n    string Encrypt(string value);\r\n}\r\n\r\npublic class MyEncryptionService\r\n{\r\n    public string Encrypt(string value)\r\n    {\r\n        //todo: return encrypted value\r\n    }\r\n\r\n    public string Decrypt(string value)\r\n    {\r\n        //todo: return the decrypted value\r\n    }\r\n}\r\n```\r\n\r\nThen, register the new implementation with the IServiceProvider\r\n\r\n```csharp\r\nbuilder.Services.AddSingleton\u003cIEncryptionService, EncryptionService\u003e();\r\n```\r\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcharleszipp%2Fazure-durable-entities-encryption","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcharleszipp%2Fazure-durable-entities-encryption","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcharleszipp%2Fazure-durable-entities-encryption/lists"}