2019 年 4 月

第 34 卷,第 4 期

[Azure 机密计算]

使用 Azure 机密计算保护多方机器学习

通过Stefano Tempesta

实现托管在公有云中,尤其是在解决方案本身的一部分存储敏感数据和知识产权的业务解决方案时,安全性极其重要。有一些最佳实践,行业已用于保护静态数据和传输,但还需要保护数据免受未经授权的访问,在使用时。Azure 机密计算 (bit.ly/2BxQkpp) 时正在处理你的数据,使用受信任执行环境 (TTEs) 提供了新的数据保护和加密级别。TEEs 实现在硬件或软件 (虚拟机监控程序) 级别,并提供受保护的处理器和内存空间的代码和数据可以运行中的完全隔离从外部应用程序和系统。TEEs 确保没有方法来查看数据或从外部,甚至使用调试器内的操作。它们甚至可以确保只有经过授权的代码有权访问数据。如果代码更改或被篡改,操作会被拒绝,并且环境禁用。TEE 强制执行的代码在其中执行中这些保护措施。

SQL Server 的安全 Enclaves Always Encrypted

在上一篇文章,"保护您的数据与 Azure 机密计算"(msdn.com/magazine/mt833273),我介绍了 Azure 机密计算并打开 Enclave SDK 用于构建软件应用程序的运行受保护的代码和受信任的执行环境中的数据。使用 Azure SQL 数据库和 SQL Server 中是相同的技术。这是始终加密功能,可确保在 SQL 数据库中的敏感数据可以加密在所有时间而不会影响 SQL 查询的功能的增强功能。始终使用安全 Enclaves 加密来实现此目标通过将敏感数据的计算委派到的 enclave,安全地解密和处理数据。与 SQL Server 2019 可用,enclave 的技术采用,名为基于虚拟化的安全 (VBS),将完全不可见的所有其他进程和 Windows OS 上的用户模式进程地址空间内的内存区域隔离开来计算机。甚至是计算机管理员无法看到 enclave 的内存。图 1显示浏览与调试器 (请注意这个问题标记,而不是实际内存内容) 的 enclave 内存时,管理员会看到。

浏览虚拟化基于使用 WinDbg 安全 Enclave
浏览虚拟化的图 1 基于使用 WinDbg 安全 Enclave

Always Encrypted 的增强的功能使用 enclaves 的方式进行了阐释图 2。SQL Server 实例包含的 enclave,加载执行数据加密,以及实现 SQL 操作的代码的代码。在提交之前对 SQL Server 引擎以进行处理的查询,客户端应用程序使用的 SQL 驱动程序发送的加密密钥至 enclave 通过安全通道。处理查询时,SQL Server 引擎在运行这些操作直接在 enclave,安全地解密和处理数据中。数据永远不会离开未加密的 enclave。

使用安全 Enclaves 始终加密到 SQL Server 通信
使用安全 Enclaves 始终加密到 SQL Server 的图 2 通信

在数据库表中的并非所有数据都需要加密。保护 enclave 中的数据可以识别的特定列。如果分析的 SQL 查询,SQL Server 引擎确定查询是否包含对需要安全 enclave 使用的加密数据的任何操作。对于安全 enclave 需要访问的查询,客户端驱动程序将发送到安全的 enclave,操作所需的特定表中的列加密密钥,然后它提交以及加密的查询执行的查询参数。标识保护列中包含的数据永远不会公开外部 enclave 明文。SQL Server 对仅在安全的 enclave 内这些列中包含的数据进行解密。如果查询包含在受保护的列的参数,这些参数在查询运行之前还解密 enclave 内。

可以使用 ALTER COLUMN 语句标识包含要加密的敏感数据的列。Enclave 内执行此语句。没有无需将数据移出数据库初始加密或其他与加密相关的架构更改。这提高了性能和可靠性的此类操作很大,并且它不需要特殊的客户端工具。假设你想要保护的患者,MedicalRecords 数据库表的年龄列中包含的期限以下语句对数据进行加密使用 AES-256 加密算法,该列中:

ALTER TABLE [dbo].[MedicalRecords]
ALTER COLUMN [Age] [char](11)
ENCRYPTED WITH (COLUMN_ENCRYPTION_KEY = [CEK1],
  ENCRYPTION_TYPE = Randomized,
  ALGORITHM = 'AEAD_AES_256_CBC_HMAC_SHA_256') NOT NULL
GO

可以找到的综合文档,新功能以及如何开始使用始终加密与在安全 Enclaves aka.ms/AlwaysEncryptedwithSecureEnclaves

多方敏感的数据源

除了 SQL Server,可能还有跨多个行业,包括财务、 零售、 政府和卫生保健的 Azure 机密计算的广泛的应用程序中。甚至竞争的组织将受益于池的专用数据集、 训练机器学习模型的聚合数据以实现更高的预测准确性。例如,运行状况研究所无法通过共享其专用的病人数据,如基因组序列和医疗记录,若要获得从机器学习跨多个数据集,而无需泄露给其他组织的数据的风险更深入的见解进行协作。具有更多的数据来训练上可使机器学习算法来生成更好的模型。可以使用适用于隐私性的机密计算: 多个参与方利用常见的机器学习服务来执行对其聚合数据。尽管运行状况研究所,在此用例,不希望其自己的数据集与任何第三方共享,但它们可以每个上传 enclave 其加密的数据、 执行远程证明、 运行机器学习代码和,最后,下载加密的机器学习模型。模型还可能进行安全评估 enclave 内通过的所有参与方,受其议定的访问控制策略保持。

图 3提供此类系统的概述。多个医院对患者的数据集,每个都有不同的密钥进行加密。医院部署一致的机器学习算法,在云数据中心内的 enclave 并使用 enclave 共享其数据密钥。Enclave 处理聚合的数据集,并输出已加密的机器学习模型。

安全多方机器学习
图 3 安全多方机器学习

在此方案中,敏感数据存储在使用始终加密保护 Enclaves 与 SQL Server 数据库并与在 TTE 中运行的机器学习服务共享。组织也使用打开的 Enclave SDK (openenclave.io) 来构建针对不同 enclave 类型的可移植 C 或 c + + 应用程序。使用 SDK,它们还利用 enclave 创建和管理、 系统基元、 运行时支持和加密的库支持使用一致的 API 和 enclaving 抽象。机器学习应用程序受益于结合使用多个数据源以生成更好的培训模型。数据保护的 SQL Server,因为它负责进行身份验证的机器学习与之共享的任何数据之前的 enclave 的 SQL 引擎。一旦进行此证明,数据是解密和机器学习而没有对其他应用程序,显示它,即使在同一个虚拟机或应用服务或托管的云平台上运行的代码中,仅对可见。

Enclave 证明

深入了解 SQL Server 引擎的安全 enclave 可以访问相应的列加密密钥和加密的数据库列中存储的敏感数据。但应用程序可以将发送到 SQL Server 的 enclave 计算涉及到的 SQL 查询之前,应该验证 enclave 是基于给定技术正版 enclave — 例如 VBS,并且在 enclave 内运行的代码经过了正确签名。验证 enclave 的过程被称为 enclave 证明,并在 SQL Server 的情况下它涉及到客户端应用程序联系的外部证明服务所使用的 SQL 客户端驱动程序。证明过程的细节取决于 enclave 技术和证明服务。SQL Server 支持在 SQL Server 2019 VBS 安全 enclaves 证明过程被称为 Windows Defender 系统防护运行时证明,使用主机保护者服务 (HGS) 作为证明服务。需要在你的环境中配置 HGS 注册托管 HGS 对 SQL Server 实例的计算机。您还需要配置 HGS 证明客户端应用程序。

若要建立信任关系各方之间,VBS enclaves 公开完全由 VBS 唯一密钥签名的 enclave 证明报表。证明服务使用此报告来建立客户端应用程序和 enclave 之间的信任关系。从根本上讲,证明涉及 enclave 报告,该身份证明和 TEE 应用程序的完整性和证明平台完整性 (其中包括主机和 TEE 的度量值)。VBS 唯一键用于链接两个,因为它用于登录报表,并存储在度量值。HGS 验证平台度量,并使用在其中密钥颁发健康证书。然后,客户端验证整个报表使用 VBS 密钥,验证 VBS 密钥本身使用健康证书,并最终还会验证它信任由 HGS 颁发健康证书。Enclave 获取的密钥来加密和解密通过安全隧道建立的客户端驱动程序和 enclave 本身的数据。通过此通道进行通信生成一个会话密钥。然后,客户端驱动程序加密列加密密钥与会话密钥和签名,并提交需要 enclave 计算的 SQL 查询。图 4扩展的证明服务的使用的 SQL Server 安全 Enclaves 使用始终加密的通信协议。

SQL Server 数据库的 enclave 证明
图 4 个 SQL Server 数据库的 Enclave 证明

若要使用始终加密安全 enclaves,应用程序必须使用支持的功能的客户端驱动程序。在 SQL Server 2019,您的应用程序应使用.NET Framework 4.6 或更高版本和.NET Framework 数据提供程序适用于 SQL Server。此外,必须使用特定于飞地类型 (例如,VBS) 和证明服务 (例如,HGS) 的安全 enclave 提供程序配置.NET 应用程序,因为使用。支持的 enclave 提供程序 NuGet 包,您需要将与你的应用程序集成单独发货。Enclave 提供程序实现客户端的逻辑,用于证明协议和建立与给定类型的安全 enclave 的安全通道。始终加密目前不支持在.NET Core 中。

分步说明,请参阅有关使用安全 enclaves 在教程中使用 SQL Server Management Studio (SSMS) 中配置 SQL Server Always Encrypted bit.ly/2Xig9nr。本教程介绍要运行以支持主机密钥证明的 HGS HGS 计算机的安装,然后向使用主机密钥证明的 HGS 注册 SQL Server 作为受保护的主机的配置。请注意,本教程的目的是创建仅用于测试目的的简单环境。主机密钥证明被建议在测试环境中使用。对于生产环境,应使用受信任的平台模块 (TPM) 证明。TPM 是一种技术设计用于提供基于硬件的安全功能。TPM 芯片是专门用于执行加密操作直接在 CPU 安全加密处理器。芯片包括多个物理安全机制,以使其篡改的对软件应用程序。如果您想要了解有关 TPM 和如何初始化 HGS 使用受信任的 TPM 证明的详细信息,可以使用启动bit.ly/2T3lVuN

若要连接到实例的 SQL Server Always Encrypted,客户端应用程序的连接字符串应包括两个附加参数:

  • 列加密设置 = 已启用
  • Enclave 证明 URL = https: / / < 你 HGS 服务器 > / 证明

例如,.NET 应用程序的连接字符串将类似于以下设置:

<connectionStrings>
  <add name="DataConnection" connectionString="Data Source=.;
    Initial Catalog=[Database Name]; Integrated Security=true;
      Column Encryption Setting = Enabled;
        Enclave Attestation URL=https://[Your-HGS-Server]/Attestation" />
</connectionStrings>

在机器学习中的预测

使用 ML.NET (dot.net/ml)、 开源和跨平台机器学习针对.NET framework 生成机器学习应用程序这篇文章中介绍。目前仍在开发中,ML.NET 允许分类和回归等机器学习任务。该框架还公开 Api 来训练模型,以及如数据结构、 转换和学习算法的核心组件。

卫生保健的用例中,机器学习应用程序实现将分类到患者的多类分类任务组可能性根据它们将开发特定疾病 (若要使内容保持较低 morbid 在这里,我将引用泛型疾病而不是专门命名一个)。与预期的此多方的数据源方案说明中,运行状况研究所共享其加密的数据集,其中包含所有必需的功能为模型定型。

机器学习代码 Web API 中开发C#。在 Visual Studio 解决方案中,添加对 Microsoft.ML NuGet 包的引用。此包包含 ML.NET 库和相关命名空间将添加到应用程序:

using Microsoft.ML;
using Microsoft.ML.Core.Data;
using Microsoft.ML.Data;

Web API 解决方案实施 POST 方法,它接受介绍医疗记录的 JSON 有效负载。在解决方案中中, 所示的 MedicalRecord 类图 5,标识了分析的 ML.NET 引擎的所有功能。风险是数据集; 的标签它是正在训练所依据的值。

图 5 MedicalRecord 类

public class MedicalRecord
{
  public float Risk { get; set; }
  public int Age { get; set; }
  public int Sex { get; set; }                // 0 = Female, 1 = Male
  public bool Smoker { get; set; }
  public ChestPainType ChestPain { get; set; }
  public int BloodPressure { get; set; }      // In mm Hg on admission to
                                              // the hospital
  public int SerumCholestoral { get; set; }   // In mg/dl
  public bool FastingBloodSugar { get; set; } // True if > 120 mg/dl
  public int MaxHeartRate { get; set; }       // Maximum heart rate achieved
}
public enum ChestPainType
{
  TypicalAngina = 1,
  AtypicalAngina,
  NonAnginal,
  Asymptomatic
}

JSON 消息请求采用以下格式:

{
  "risk": 0.0,
  "age": 0,
  "sex": 0,
  "smoker": false,
  "chestPain": 0,
  "bloodPressure": 0,
  "serumCholestoral": 0,
  "fastingBloodSugar": false,
  "maxHeartRate": 0
}

分类类实现的多类分类任务的输入,在给定的医疗记录时将该患者分配给的侵袭疾病的风险类。此过程开发的以下四个步骤:

  1. 实例化一个 MLContext 对象,表示 ML.NET 上下文类。
  2. 训练该模型根据 SQL Server 中提供的历史数据集 (和受保护的 enclave 内)。
  3. 评估模型。
  4. 为其评分。

在窗体的 JSON 响应中返回到客户端应用程序 (运行状况 institute) 的输出:

{
  "score": 0.0,
  "accuracy": 0.0
}

但让我们按顺序,描述每个步骤在机器学习代码。第一步是创建的 MLContext 实例作为分类类,使用随机种子的一部分 (种子:0) 为跨多个培训可重复且具有确定性的结果。MLContext 是用于访问源数据和训练的模型,以及相关的机器学习变压器和房产您引用的对象:

public Classification()
{
  _context = new MLContext(seed: 0);
}
private MLContext _context;

机器学习过程的下一步定型模型,如中所示图 6。这是将数据加载从 SQL Server 数据库中的安全 enclave 的步骤。使用 SqlConnection 类,它在内部制定的证明和与 enclave 之间的通信通过安全通道创建与 SQL Server 的连接。

图 6 训练模型

public IEnumerable<MedicalRecord> ReadData(int split = 100)
{
  IEnumerable<MedicalRecord> medicalRecords = new List<MedicalRecord>();
  using (var connection = new SqlConnection(ConnectionString))
  {
    connection.Open();
    using (SqlCommand cmd = connection.CreateCommand())
    {
      cmd.CommandText = SqlQuery(split);
      using (SqlDataReader reader = cmd.ExecuteReader())
      {
        if (reader.HasRows)
        {
          while (reader.Read())
          {
            medicalRecords.Append(ReadMedicalRecord(reader));
          }
        }
      }
    }
  }
  return medicalRecords;
}

请注意用于从 SQL Server 中使用 tablesample 功能的数据库选择记录的一个百分比的拆分参数。训练和评估模型的要求不同的数据子集作为输入。准确估算是用于定型,具体取决于其质量分配 80%的数据。输入,质量越高越好的预测准确性:

private static string SqlQuery(int split) =>
  $"SELECT [Age], [Sex], [Smoker], [ChestPain],
    [BloodPressure], [SerumCholestoral], [FastingBloodSugar],
      [MaxHeartRate] FROM [dbo].[MedicalRecords] tablesample({split} percent)";

数据随后被加载到当前的 ML 上下文,并使用预测训练的线性多类分类模型中使用的随机双坐标上升 (SDCA) 算法,用于解决过程的目标的方法获取训练的模型大规模监督式的学习的问题。多类分类培训师实际"fit"; 前添加到管道的培训师也就是说,模型的训练发生前。ML.NET 转换使用的应用自定义转换之前定型或测试的进程链的数据。

中所示的 TrainModel 方法中的转换的目的图 7,是指定的机器学习算法识别的格式的标签源数据。若要完成此特征化的数据,转换管道将合并所有特征列到使用 concatenate 方法的功能列。但在此之前,我需要将任何非浮点型数据以浮点数据类型,正如所有 ML.NET 学习器都期望的功能是 float 向量转换。

图 7 获取训练的模型

public void TrainModel(IDataSource<MedicalRecord> dataSource, Stream targetStream)
{
  IEnumerable<MedicalRecord> sourceData = dataSource.ReadData(80); 
    // 80% of records for training
  IDataView trainData = _context.Data.ReadFromEnumerable<MedicalRecord>(sourceData);
  // Convert each categorical feature into one-hot encoding independently
  var transformers = _context.Transforms.Categorical.OneHotEncoding(
    "MedicalRecordAge", nameof(MedicalRecord.Age))
    .Append(_context.Transforms.Categorical.OneHotEncoding(
      "MedicalRecordSex", nameof(MedicalRecord.Sex)))
    .Append(_context.Transforms.Categorical.OneHotEncoding(
      "MedicalRecordSmoker", nameof(MedicalRecord.Smoker)))
    .Append(_context.Transforms.Categorical.OneHotEncoding(
      "MedicalRecordChestPain", nameof(MedicalRecord.ChestPain)))
    .Append(_context.Transforms.Categorical.OneHotEncoding(
      "MedicalRecordBloodPressure", nameof(MedicalRecord.BloodPressure)))
    .Append(_context.Transforms.Categorical.OneHotEncoding(
      "MedicalRecordSerumCholestoral", nameof(
        MedicalRecord.SerumCholestoral)))
    .Append(_context.Transforms.Categorical.OneHotEncoding(
      "MedicalRecordFastingBloodSugar", nameof(
        MedicalRecord.FastingBloodSugar)))
    .Append(_context.Transforms.Categorical.OneHotEncoding(
      "MedicalRecordMaxHeartRate", nameof(MedicalRecord.MaxHeartRate)));
  var processChain = _context.Transforms.Concatenate(DefaultColumnNames.Features,
      nameof(MedicalRecord.Age),
      nameof(MedicalRecord.Sex),
      nameof(MedicalRecord.Smoker),
      nameof(MedicalRecord.ChestPain),
      nameof(MedicalRecord.BloodPressure),
      nameof(MedicalRecord.SerumCholestoral),
      nameof(MedicalRecord.FastingBloodSugar),
      nameof(MedicalRecord.MaxHeartRate)
  ).AppendCacheCheckpoint(_context);
  var trainer =
    _context.MulticlassClassification.Trainers.StochasticDualCoordinateAscent(
      labelColumn: DefaultColumnNames.Label,
        featureColumn: DefaultColumnNames.Features);
  var pipeline = processChain.Append(trainer);
  var model = pipeline.Fit(trainData);
  _context.Model.Save(model, targetStream);
}

医疗记录中的所有功能本质上是类别和不 float 值。因此,将它们连成单个输出列之前, 我分类对应用转换使用 OneHotEncoding 函数每个。默认情况下,学习算法处理只有从功能列的功能。AppendCacheCheckpoint 方法在缓存源数据,因此当循环访问多次使用缓存的数据时,可能得到更好的性能。调用上估算器管道的适合性的方法时发生的实际培训。房产从数据中学习,并生成机器学习模型。适合的方法将返回要用于预测的模型。最终可以将训练的模型保存到一个流,以便将来的使用率。

以下模型定型、 模型评估对于确保良好质量的下一步,模型评分,这是对结果进行预测至关重要。针对数据集获取作为定型模型,如中所示,使用源数据的百分比 (在此事例 20%),从测试数据的转换执行的预测数据计算图 8。在当前 ML.NET 上下文中定义的 MulticlassClassification 对象的 Evaluate 方法计算在模型中使用指定的数据集的质量度量值。它返回 MultiClassClassifierMetrics 对象,其中包含由多类分类评估器计算的整体度量值。在示例中,我将计算百分比的计算结果的记录总数超出正确预测的准确性。TopKAccuracy 指标描述相对的一些示例,其中 true 标签是一个 top K 预测标签。

图 8 评估模型

public double EvaluateModel(IDataSource<MedicalRecord> dataSource,
  Stream modelStream)
{
  IEnumerable<MedicalRecord> sourceData = dataSource.ReadData(20); 
    // 20% of records for evaluation
  var testData =
    _context.Data.ReadFromEnumerable<MedicalRecord>(sourceData);
  var predictions = _context.Model.Load(modelStream).Transform(testData);
  var metrics = _context.MulticlassClassification.Evaluate(
    data: predictions, label: DefaultColumnNames.Label,
      score: DefaultColumnNames.Score,
        predictedLabel: DefaultColumnNames.PredictedLabel, topK: 0);
  return metrics.TopKAccuracy / metrics.TopK * 100.0 / sourceData.Count();
}

分类 API 中的最后一步是评分模型并生成与给定的医疗记录用户标识存在风险的预测。从加载数据模型之前训练并保存,评分模型开始,然后创建从,预测引擎已训练模型。在评分方法中,我加载训练的模型,然后与医疗记录和风险预测类型调用 CreatePredictionEngine 函数 (MedicalRecord 和 RiskPredictionC#类,分别)。预测引擎生成评分,用于标识与分析医疗记录的患者风险的类:

public double Score(MedicalRecord medicalRecord, Stream modelStream)
{
  ITransformer trainedModel = _context.Model.Load(modelStream);
  var predictionEngine = trainedModel.CreatePredictionEngine<MedicalRecord,
    RiskPrediction>(_context);
  var prediction = predictionEngine.Predict(medicalRecord);
  return prediction.Score;
}

RiskPrediction 对象包含的分数和准确性返回 Web API 的 Post 方法的属性。对于评分属性中,我添加了 ColumnName 特性告知 ML.NET,这是我想要输出的预测引擎的预测方法生成的已评分的值:

public class RiskPrediction
{    [ColumnName("Score")]
  public double Score;
  public double Accuracy;
}

最后,如中所示图 9,卫生保健的 Web API 的 Post 方法处理序列中的所有这些步骤:

  1. 获取 MedicalRecord 对象的 json 表示形式。
  2. 实例化分类器、 ML.NET 用于多类分类。
  3. 训练和保存模型。
  4. 计算其准确性
  5. 预测与输入中提供的医疗记录关联的风险。

图 9 预测特定的医疗记录的风险

public IHttpActionResult Post(string medicalRecordJson)
{
  MedicalRecord medicalRecordObj =
    JsonConvert.DeserializeObject<MedicalRecord>(medicalRecordJson);
  Classification classification = new Classification();
  FileStream modelStream = new FileStream("[Path]", FileMode.Create);
  classification.TrainModel(new MedicalRecordDataSource(), modelStream);
  double accuracy = classification.EvaluateModel(
    new MedicalRecordDataSource(), modelStream);
  double score = classification.Score(medicalRecordObj, modelStream);
  RiskPrediction prediction = new RiskPrediction
  {
    Score = score,
    Accuracy = accuracy
  };
  return Json<RiskPrediction>(prediction);
}

请考虑此代码的性能改进,例如缓存供将来使用训练的模型中的边距。可以跳过模型训练和评估,使用预先训练的模型,从而显著提高了性能时。

在我的测试,我尝试对单个数据集,通过运行状况研究所获得运行预测过程获取平均精确到 90%。每个数据集具有大约 100,000 的记录。当将多个数据集组合到单个的一个,准确性达到 96%。

总结

在本文中,我演示了机器学习应用程序如何通过利用更广泛的数据集,通过从多个受信任的源收集数据,而不会影响在所有参与方之间共享信息的机密性生成更好的预测涉及。这被通过保护由机器学习中 SQL Server Always Encrypted 的 enclave,即 Azure 机密计算技术的一部分的代码中使用的数据。机器学习解决方案从不同的受保护源收集的数据集,并通过将数据合并到更大的数据集,获取更高版本上训练的模型预测的准确性。

注意,机密计算要求代码以在 TEE 中运行它。在本文中介绍的示例中,SQL 客户端驱动程序是与 SQL Server 的受信任的执行环境 intermediator。ML.NET 代码,因此,可能会或可能不能在 TEE 内运行。如果是这样,它称为安全多方机器学习计算。多方计算意味着有两个或多个参与方的相互排斥信任具有数据和/或代码他们想要对每个其他保护。在此上下文中,参与方希望执行计算总以生成共享的输出,而无需任何敏感数据泄漏。Enclave 充当受信任 intermediator 为此计算。

整个解决方案是在 GitHub 上提供bit.ly/2Exp78V


Stefano Tempesta是 Microsoft 区域总监,MVP AI 和业务应用程序和区块链委员会的成员。在国际 IT 会议,包括 Microsoft Ignite 和技术大会上发表演讲 Tempesta 的兴趣扩展到区块链和 AI 相关技术。他创建了 Blogchain 空间 (blogchain.space),有关区块链技术博客的 MSDN 杂志 》 和 MS Dynamics 世界中,将写入,并将发布 Azure AI 库中的机器学习试验 (gallery.azure.ai)。

衷心感谢以下 Microsoft 技术专家对本文的审阅:Gleb Krivosheev, Simon Leet
Simon Leet 是在 Azure 机密计算产品组的首席工程师。