You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

迁移至Azure后,Blob Storage中PGP加解密免费实现方案咨询

基于Azure Function和Blob Storage的PGP免费解密实现方案

核心思路

PGPCore本身支持流操作,无需依赖本地文件。我们可以直接读取Blob存储中的加密文件流,通过PGPCore解密后,将解密后的流直接写回Blob存储,全程避免本地文件操作,完美适配Azure无服务器环境。

实现步骤与代码示例

1. 依赖包安装

确保项目中安装以下NuGet包:

  • PGPCore(免费PGP处理库)
  • Azure.Storage.Blobs(Blob存储操作)
  • Azure.Security.KeyVault.Secrets(Key Vault密钥读取)
  • Azure.Identity(Azure服务身份验证)

2. PGP流解密工具类

封装通用的流解密逻辑,避免重复代码:

using PgpCore;
using System.IO;
using System.Threading.Tasks;

public static class PgpDecryptor
{
    public static async Task<Stream> DecryptStreamAsync(Stream encryptedStream, string privateKey, string passphrase)
    {
        using var pgp = new PGP();
        var decryptedStream = new MemoryStream();
        
        // 将私钥字符串转换为流
        using var privateKeyStream = new MemoryStream(System.Text.Encoding.UTF8.GetBytes(privateKey));
        // 执行流对流传密
        await pgp.DecryptStreamAsync(encryptedStream, decryptedStream, privateKeyStream, passphrase);
        
        decryptedStream.Position = 0; // 重置流指针,确保后续读取从头开始
        return decryptedStream;
    }
}

3. Azure Blob触发器函数实现

编写Blob触发的Function,完成从Blob读取、解密、写回的全流程:

using Azure.Storage.Blobs;
using Azure.Security.KeyVault.Secrets;
using Microsoft.Azure.Functions.Worker;
using Microsoft.Extensions.Logging;
using System.IO;
using System.Threading.Tasks;

public class BlobPgpDecryptFunction
{
    private readonly BlobServiceClient _blobServiceClient;
    private readonly SecretClient _secretClient;

    // 通过依赖注入获取服务客户端
    public BlobPgpDecryptFunction(BlobServiceClient blobServiceClient, SecretClient secretClient)
    {
        _blobServiceClient = blobServiceClient;
        _secretClient = secretClient;
    }

    [Function("BlobPgpDecrypt")]
    public async Task Run(
        [BlobTrigger("pgp-uploads/{name}", Connection = "BlobStorageConnection")] Stream inputBlob,
        string name,
        ILogger log)
    {
        log.LogInformation($"开始处理PGP加密文件: {name}");

        // 从Key Vault获取私钥和密码
        var privateKeySecret = await _secretClient.GetSecretAsync("pgp-private-key");
        var passphraseSecret = await _secretClient.GetSecretAsync("pgp-passphrase");
        string privateKey = privateKeySecret.Value.Value;
        string passphrase = passphraseSecret.Value.Value;

        try
        {
            // 解密加密流
            using var decryptedStream = await PgpDecryptor.DecryptStreamAsync(inputBlob, privateKey, passphrase);

            // 生成解密后的文件名(替换后缀为.txt)
            string outputFileName = Path.ChangeExtension(name, ".txt");
            var outputBlobClient = _blobServiceClient
                .GetBlobContainerClient("pgp-uploads")
                .GetBlobClient(outputFileName);

            // 将解密后的流上传回Blob存储
            await outputBlobClient.UploadAsync(decryptedStream, overwrite: true);
            log.LogInformation($"解密完成,文件已保存: {outputFileName}");
        }
        catch (Exception ex)
        {
            log.LogError(ex, $"解密文件 {name} 失败");
            // 可扩展:将失败文件移至专门的错误容器,便于排查
            throw;
        }
    }
}

4. 服务配置(.NET 6+孤立模型)

在Program.cs中配置依赖注入,确保Function能获取Blob和Key Vault客户端:

using Microsoft.Azure.Functions.Worker;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Azure.Identity;

var host = new HostBuilder()
    .ConfigureFunctionsWorkerDefaults()
    .ConfigureServices(services =>
    {
        services.AddAzureClients(clientBuilder =>
        {
            // 配置Blob存储客户端
            clientBuilder.AddBlobServiceClient(
                Environment.GetEnvironmentVariable("BlobStorageConnection"));
            
            // 配置Key Vault客户端,使用托管身份验证
            clientBuilder.AddSecretClient(
                new Uri(Environment.GetEnvironmentVariable("KeyVaultUri")))
                .WithCredential(new DefaultAzureCredential());
        });
    })
    .Build();

host.Run();

关键注意事项

  • 流指针重置:解密后的流必须重置Position到0,否则上传时会因流处于末尾而写入空内容。
  • 权限配置:确保Function的托管身份拥有:
    • Key Vault的Secret Get权限
    • Blob Storage的Blob Contributor权限
  • 大文件处理:如果处理超大文件,建议避免使用MemoryStream,可改用Azure Function临时存储的FileStream,防止内存溢出。
  • 异常排查:添加失败文件迁移逻辑,将解密失败的文件移至单独容器,便于后续分析问题。

内容的提问来源于stack exchange,提问作者Caverman

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 07:35:36