C# 密码学高级教程(五)

原文:Pro Cryptography and Cryptanalysis

协议:CC BY-NC-SA 4.0

十三、同态加密

同态加密(HE)代表一种支持对加密数据进行计算的加密技术,在计算时不需要解密。对明文数据应用的计算结果必须与通过对加密数据应用反映对明文数据应用的相应计算而获得的结果的解密结果相同。这些类型的加密方案有很大的潜力,因为第三方可以在加密数据上计算函数(并因此应用算法),而无需访问明文数据。因此,数据得到处理,同时其隐私和安全得到保证。例如,您正在旅行,想要搜索附近的餐馆。这个简单的搜索可能会透露您的信息,例如您在哪个城镇以及您搜索的时间。如果搜索引擎使用同态加密方案,那么其他人就看不到你的任何信息,你收到的搜索结果也是如此。可能使用同态加密的重要领域包括金融/商业部门、医疗保健和其他使用敏感数据的领域。

如果一个函数 f : AB 满足以下性质,则称它在运算“”上是同态的:*

)

除了密钥生成、加密和解密,同态加密方案还有一个算法Eval (,称为评估,它将加密数据作为输入,并输出加密数据。在Eval算法中,函数f应用于加密数据c1 和c2,而不访问普通数据m1 和m2,具有以下属性:

)

在同态加密中,同态被认为仅用于加法和乘法这两种数学运算,因为对应于函数的任何电路都可以使用对应于这两种运算的门来表示。同态加密在Unpadded RSA算法中遇到的第一个观察,同态运算是乘法,

)

)

)

其中 m 1m 2 是两个普通消息, Enc 代表加密功能。

有三种同态加密方案:

  • 部分同态加密(PHE) 。接受单个操作的次数不限。代表其他加密方案基础的重要 PHE 方案是 RSA [1 ]、Goldwasser-Micali [2 ]和 El-Gamal [3 ]。

  • 有点同态加密(SWHE) 。接受有限次数的多重操作。一个 SWHE 方案的例子是 [4 ]。

  • 全同态加密(FHE) 。接受多次操作,次数不限。FHE 被称为“密码学的圣杯”或“密码学的瑞士军刀” 5 因为它可以对加密数据应用任意次数的函数。第一个 FHE 方案是在 2009 年提出的,它基于理想晶格 [6 ]。虽然这个计划有很大的潜力,并为 FHE 开辟了道路,但它也有一些缺点,比如它的复杂性和抽象性,这使得它在最初的形式下不切实际。此外,许多研究使用 [6 中提出的 FHE 通用框架来创建或改进完全同态方案。

全同态加密

深入了解 FHE 是值得的,因为它是一项伟大的技术,有可能解决(几乎)所有的安全、隐私和保密问题。

第一个 FHE 方案是在 2009 年提出的,基于理想格 [6 ]和理想陪集问题硬度假设,随后又有许多其他方案提出,为第一代 FHE 方案开辟了道路。紧随其后的工作是 [7 ],其中作者提出了一个更简单的基于整数运算的 FHE 方案。然而,这两种方案的缺点是快速的噪声增长,这对实际实现和安全性有很大的影响,并且限制了同态能力。此外,噪音的增长在某种程度上也使得解密变得不可能。

第二代开始采用更有效地控制噪声的方案 [8 , [9 ],这在某些条件下带来了更好的性能和更强的安全性(称为硬度假设)。这一代产生了支持给定多项式深度的电路评估的分级方案,以及能够产生 FHE 方案的自举方案。如果加密方案可以评估它自己的解密电路以及一个与非门,则该加密方案称为可自举的。

第三代从 [10 开始,引入了全新的噪点处理方式。第二代方案比第三代方案提供了更好的效率,但第三代方案的硬度假设可能较弱。从第三代开始的很多方案都是基于非对称乘法,也就是说,对于两个密文 c 1c 2c1c2的乘积不同于c2∙c

FHE 在密码学方面有更多的应用:

  • 外包。存储和计算可以外包,而不会泄露私人信息。例如,一家小公司希望将其数据存储在云中,但它应该对数据进行加密,以防止云提供商访问这些数据。FHE 在这方面会有所帮助,因为云提供商可能会以加密格式处理公司的数据,而无法访问明文数据。此外,云提供商还会将计算结果以加密格式发送给数据所有者,只有私钥持有者才能解密。

  • 私人信息检索 (PIR) 私人查询。这些在数据库查询或搜索引擎中是很重要的,例如,当客户机想要向存储在服务器上的大型数据库提交查询时,但是客户机不希望服务器了解关于查询的任何信息。因此,客户端对查询进行加密,并发送给服务器;然后,服务器对加密数据应用加密查询,并用加密结果进行响应。

  • 两个实体之间的一般计算(双方计算)。让我们假设有两方,每一方都拥有一个私有输入,A方的xB方的y,以及一个双方都知道的约定函数F。当第A方想要计算拥有的输入的函数时,它将带来x并计算r = F(x, y),并且它将学习结果r,但是将不会学习关于y的任何东西。另一方面,B方将不会了解到关于xr的任何信息。在一个半诚实的模型中,这将等同于B计算F y (x),其中A加密x并发送给B,因为语义安全保证了这样一个事实,即B不会了解到与x相对应的普通值。如果在这里使用同态加密来评估函数,A将只学习F(x,y)的结果,而不学习其他任何东西。

  • 零知识。零知识证明协议可以使用同态加密来在 NP(非确定性多项式时间)中对每种语言 L 应用它。

微软海豹突击队公司实施的 FHE 方案

BFV [11 和 CKKS [12 加密方案在微软的 FHE 库中实现,分别叫做SEAL [13 , 14 。

在 [11 ]中,加密函数定义在次数最大的多项式集合n上,系数以 t 为模计算。该集合表示为rt=t[x]/(xn+另一方面,密文位于 R q 集合中,其中多项式的系数取模q。该方案中的同态运算是加法和乘法,保留了 R t 的环结构。要加密一个普通值,应该首先使其成为结构 R t 接受的多项式形式。在 11 中提出的方案的算法是SecretKeyGen(基于安全参数生成密钥)、PublicKeyGen(基于密钥生成公钥)、EvaluationKeyGen(基于密钥生成评估密钥)、Encrypt(使用公钥加密普通值)、Decrypt(使用密钥解密加密值)、Add(执行两个加密值的加法)和Multiply(执行两个加密值之间的乘法)。注意加法和乘法的结果必须落在同一个结构 R q 。更多细节和理论方面的内容请咨询 [11 ]。

虽然 [11 提供了一种对整数应用模运算的方法,但在 [12 中,作者也提供了对实数和复数应用模运算的方法。无论如何,在 [12 中,结果是近似的,但这些技术是以加密格式对实数求和、对加密数据应用机器学习算法或计算加密位置之间距离的最佳技术之一。

海豹突击队图书馆

SEAL的名字来源于简单加密算法库 [15 ],写在C++中。SEAL的最新稳定版本是 3.5(2020 年 5 月发布),它支持 .NET 标准包装器,使得使用公共 API 更容易,也更容易被非密码学专家使用。该库有一个 GitHub 页面 [16 ],可以从那里下载。

SEAL库是独立的,它不像其他 FHE 方案实现那样需要外部库。这使事情变得更容易,因为它包含自动选择加密方案参数的模块和噪声估计模块。在 [17 中,证明了海豹突击队 v2.0 在双重格攻击下是安全的。

安装海豹突击队库最简单的方法是使用 Visual Studio 中的 NuGet 包管理器控制台(本章我们将使用 Windows 10 Education x64 上的 Visual Studio 2019 社区)。

在 Visual Studio 中创建新项目(我们创建了一个名为SEALDemo的项目,其类型为ConsoleApp(.NET Core))然后打开选择Tools > NuGet Package Manager > Package Manager Console,并键入

PM> Install-Package Microsoft.Research.SEALNet -Version 3.5.6

如果安装成功,控制台上会显示类似图 13-1 的信息。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 13-1

使用软件包管理器控制台安装海豹突击队

在继续之前,我们重复海豹突击队的 GitHub 页面上的警告:

“如果不阅读所有示例或简单地重复使用示例中的代码,就不可能正确使用微软海豹突击队。任何试图这样做的开发人员都不可避免地会产生易受攻击、故障或极其缓慢的代码。”

——https://github.com/microsoft/SEAL/blob/master/README.md#getting-started

在新创建的项目中,添加一个名为Example的新类,并在这个类中添加static void方法EasyExample()。代码应该如清单 13-1 所示。

using System;
using System.Collections.Generic;
using System.Text;

namespace SEALDemo
{
    class Example
    {
        public static void EasyExample()
        {
        }
    }
}

Listing 13-1The Initial Structure

请注意,当您创建一个新类时,库SystemSystem.Collections.GenericSystem.Text会自动添加。对于 Visual Studio 的其他版本,这些库可能会有所不同,或者根本不会出现。删除上面的三条指令,用Microsoft.Research.SEAL;代替。这样,你就可以在你的类中使用海豹突击队库中的方法。

此外,让我们使用 BFV 加密方案将代码添加到EasyExample()方法中,并添加来自SEAL库的功能。首先,您需要指定加密参数。它们是多项式模数的次数(n)、密文的系数模数(q)和明文的模数(t)。为了告诉应用您想要定义 BFV 方案的参数,您在EasyExample()中添加清单 13-2 中的以下代码行。

EncryptionParameters parameters = new EncryptionParameters(SchemeType.BFV);

Listing 13-2Defining the BFV Parameters

接下来,您需要为每个参数提供值。多项式模次数的值代表2的一次幂,实际上就是一个分圆多项式1的次数。这个度数的推荐范围是{1024, 2048, 4096, 8192, 16384, 32768}。该值越高,对加密数据的计算就越困难,但速度会变得更慢。中间值是 4096,这允许合理的计算次数,所以为您的应用选择这个值。下一个参数是密文系数模数,代表一个大整数。它应该表示为素数的乘积,其位数应该是其素数因子的位数之和。该值越高,支持的加密计算越多。总之,在多项式模次数和系数模的最大比特长度之间存在一种关系。例如,多项式模次数的值 4096 对应于系数模的比特大小的值 109。最后一个参数是明文的模数,通常是一个正整数。在本例中,您将使用 2 的幂对其进行初始化。在其他情况下,模数应该是一个质数。该值的目的是给出普通数据的位大小,并设置乘法运算的消耗限制。有关加密参数的更多信息可在 [13 和 [14 中找到。

我们需要解释的另一个概念是**噪声预算*,用位数表示。简而言之,初始噪声预算*由加密参数给出,并且在同态运算(加法和乘法)期间消耗噪声的速率也由加密参数给出。系数模的值对初始噪声预算有重要影响;系数模数值越高,初始噪声预算值越高。如果加密值的噪声预算达到值 0,则密文不能再被解密,因为噪声量太高。

**回到示例,在EasyExample()方法中添加清单 13-3 中的以下初始化:

parameters.PolyModulusDegree = 4096;
parameters.CoeffModulus = CoeffModulus.BFVDefault(4096);
parameters.PlainModulus = new Modulus(1024);

Listing 13-3Initialization

使用海豹突击队上下文检查加密参数的正确性:

SEALContext SEALctx = new SEALContext(parameters);

接下来的步骤更容易。您需要实例化提供 BFV 加密方案算法的类,如清单 13-4 所示。

KeyGenerator keyGenerator = new KeyGenerator(SEALctx);
PublicKey pK = keyGenerator.PublicKey;
SecretKey sK = keyGenerator.SecretKey;
Encryptor encrypt = new Encryptor(SEALctx, pK);
Evaluator evaluate = new Evaluator(SEALctx);
Decryptor decrypt = new Decryptor(SEALctx, sK);

Listing 13-4Instantiate the Classes for BFV

举个简单的例子,我们对多项式p(x)= 3x4+6x3+9x2+12x+6 求值 x = 3。

为了检查加密和解密是否有效,让我们加密值 x = 3,然后解密结果。同时,您检查一些度量标准(清单 13-5 )。

int value = 3;
Plaintext plainValue = new Plaintext(value.ToString());
Console.WriteLine($"The value = {value} is expressed as a plaintext polynomial 0x{plainValue}.");
Console.WriteLine();
Ciphertext encryptedValue = new Ciphertext();
encrypt.Encrypt(plainValue, encryptedValue);
Console.WriteLine($"- the size of the freshly encrypted value is: {encryptedValue.Size}");
Console.WriteLine("- the initial noise budget of the encrypted value: {0} bits",
      decrypt.InvariantNoiseBudget(encryptedValue));
Plaintext decryptedValue = new Plaintext();
Console.Write("- the decryption of encrypted value: ");
decrypt.Decrypt(encryptedValue, decryptedValue);
Console.WriteLine($"0x{decryptedValue}");

Listing 13-5Encryption of x=3 and Metrics Checking

现在您应该运行应用了。为此,您需要转到您的解决方案中的Program类(清单 13-6 ,并调用EasyExample()方法:

public class Program
{
   static void Main(string[] args)
   {
      Example.EasyExample();
      GC.Collect();
   }
}

Listing 13-6The Main Method

清单 13-6 中需要GC.Collect,因为它准确地显示了内存池的使用情况。运行该应用,您将获得如清单 13-7 和图 13-2 所示的输出。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 13-2

运行应用的结果

The value = 3 is expressed as a plaintext polynomial 0x3.

- the size of the freshly encrypted value is: 2
- the initial noise budget of the encrypted value: 55 bits
- the decryption of encrypted value: 0x3

Listing 13-7The Result of Running the Application

让我们回到加密/解密验证。通过Plaintext构造函数,普通值被转换成比模数多项式阶数更低的多项式,其系数被表示为十六进制值。使用海豹突击队库得到的密文被表示为两个或更多的多项式,这些多项式的系数被计算为整数模来自CoeffModulus的素数相乘的结果。您用对象encryptedValue实例化了Ciphertext类,其中您放置了plainValue的加密。您可以使用encrypt对象的Encrypt方法来实现。很容易观察到,Encrypt方法在这里有两个参数:表示明文值的源的参数(plainValue)和表示源明文值的加密目的地的第二个参数(encryptedValue)。密文的大小由多项式的个数给出,新加密的密文的大小总是 2。该值由encryptedValue对象的Size方法返回。此外,decrypt对象的InvariantNoiseBudget方法为我们计算了普通值3加密的初始噪声预算。InvariantNoiseBudget被实现到Decryptor类中,因为它显示了解密是否会在你的计算中的某一点起作用。要解密结果,使用由decrypt对象调用的Decrypt方法。最后,解密确实有效,因为十六进制表示中的值0x3表示3

为了优化工作,建议采用乘法运算较少的多项式形式,因为乘法运算成本较高,可以更快地降低噪声预算。因此, p ( x )可能被因式分解为p(x)= 3(x2+2)(x+1)2,也就是说你会先求值( x 2 + 2),再求值( x + 1)

要计算( x 2 + 2),如清单 13-8 所示进行。

Console.WriteLine("Compute squareValuePlusTwo (x²+2).");
Ciphertext squareValuePlusTwo = new Ciphertext();
evaluate.Square(encryptedValue, squareValuePlusTwo);
Plaintext plainTextTwo = new Plaintext("2");
evaluate.AddPlainInplace(squareValuePlusTwo, plainTextTwo);

Console.WriteLine($"- the size of squareValuePlusTwo:
      {squareValuePlusTwo.Size}");
Console.WriteLine("- the noise budget in plainTextTwo: {0} bits",
      decrypt.InvariantNoiseBudget(squareValuePlusTwo));

Plaintext decryptedResult = new Plaintext();
Console.Write("- the decryption of squareValuePlusTwo: ");
decrypt.Decrypt(squareValuePlusTwo, decryptedResult);
Console.WriteLine($"0x{decryptedResult}");

Listing 13-8Computing (x2 + 2) 

清单 13-9 和图 13-3 显示了运行应用后的输出。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 13-3

计算的结果(x2+2)

Compute squareValuePlusTwo (+2).
- the size of squareValuePlusTwo: 3
- the noise budget in squareValuePlusTwo: 33 bits
- the decryption of squareValuePlusTwo: 0xB

Listing 13-9The Result of Computing (x2 + 2)

确实,如果计算 3 2 + 2,得到11,其十六进制表示为0xB;噪声预算大于 0,所以解密仍然有效。请注意,evaluate对象允许您直接对加密数据进行操作。本例中的收集器变量是squareValuePlusTwo。首先,你用Square的方法将2幂的加密值,即x2 放入这个变量。接下来,您添加一个明文值2,使用方法AddPlainInplace,导致 x 2 + 1。注意,在这个例子中, x = 3。此外,SquareAddPlainInplace方法有两个参数,一个源和一个目的。

类似地,您计算( x + 1) 2 ,使用作为收集器变量valuePlusOneSquare,如清单 13-10 所示。

Console.WriteLine("Compute valuePlusOneSquare ((x+1)²).");
Plaintext plainTextOne = new Plaintext("1");
Ciphertext valuePlusOneSquare = new Ciphertext();
evaluate.AddPlain(encryptedValue, plainTextOne,
       valuePlusOneSquare);
evaluate.SquareInplace(valuePlusOneSquare);
Console.WriteLine($"- the size of valuePlusOneSquare:
       {valuePlusOneSquare.Size}");
Console.WriteLine("- the noise budget in valuePlusOneSquare:
       {0} bits", decrypt.InvariantNoiseBudget(valuePlusOneSquare));
Console.Write("- decryption of valuePlusOneSquare: ");
decrypt.Decrypt(valuePlusOneSquare, decryptedResult);
Console.WriteLine($"0x{decryptedResult}");

Listing 13-10Computing (x + 1)2 

清单 13-11 和图 13-4 显示了运行应用的结果。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 13-4

计算的结果( x + 1) 2

Compute valuePlusOneSquare ((x+1)²).
- the size of valuePlusOneSquare: 3
- the noise budget in valuePlusOneSquare: 33 bits
- decryption of valuePlusOneSquare: 0x10

Listing 13-11The Result of Computing (x + 1)2

确实,如果计算(3 + 1) 2 ,得到10,其十六进制表示为0x10;噪声预算大于 0,所以解密仍然有效。

3(x2+2)(x+1)2的最终结果被收集到encryptedOutcome变量中,如清单 13-12 所示。

Console.WriteLine("Compute encryptedOutcome 3(x² + 2)(x + 1)² .");
Ciphertext encryptedOutcome = new Ciphertext();
Plaintext plainTextThree = new Plaintext("3");
evaluate.MultiplyPlainInplace(squareValuePlusTwo, plainTextThree);
evaluate.Multiply(squareValuePlusTwo, valuePlusOneSquare, encryptedOutcome);
Console.WriteLine($"- size of encryptedOutcome:
      {encryptedOutcome.Size}");
Console.WriteLine("- the noise budget in encryptedOutcome:
      {0} bits", decrypt.InvariantNoiseBudget(encryptedOutcome));
decrypt.Decrypt(encryptedOutcome, decryptedResult);
Console.WriteLine("- decryption of 3(x²+2)(x+1)² = 0x{0}",
decryptedResult);

Listing 13-12Computing 3(x2 + 2)(x + 1)2

清单 13-13 和图 13-5 显示了结果。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 13-5

计算 3 的输出(x2+2)(x+1)2

Compute encryptedOutcome 3(+ 2)(x + 1)² .
- size of encryptedOutcome: 5
- the noise budget in encryptedOutcome: 2 bits
- decryption of 3(+2)(x+1)² = 0x210

Listing 13-13The Output of Computing 3(x2 + 2)(x + 1)2

的确,如果你计算 3(3 2 + 2)(3 + 1) 2 ,我们得到528。别忘了明文模数是1024,所以528 mod 1024 = 528,它有0x210的十六进制表示。噪声预算大于 0,这允许您解密最终的加密结果。

清单 13-14 将所有这些放在一起。

class Example
{
  public static void EasyExample()
  {
    EncryptionParameters parameters = new
    EncryptionParameters(SchemeType.BFV);

    parameters.PolyModulusDegree = 4096;
    parameters.CoeffModulus = CoeffModulus.BFVDefault(4096);
    parameters.PlainModulus = new Modulus(1024);

    SEALContext SEALctx = new SEALContext(parameters);

    KeyGenerator keyGenerator = new KeyGenerator(SEALctx);
    PublicKey pK = keyGenerator.PublicKey;
       SecretKey sK = keyGenerator.SecretKey;
       Encryptor encrypt = new Encryptor(SEALctx, pK);
       Evaluator evaluate = new Evaluator(SEALctx);
       Decryptor decrypt = new Decryptor(SEALctx, sK);

       Console.WriteLine("Evaluation of 3(x² + 2)(x + 1)²");
       Console.WriteLine();
       int value = 3;
       Plaintext plainValue = new Plaintext(value.ToString());
       Console.WriteLine($"The value = {value} is expressed as
             a plaintext polynomial 0x{plainValue}.");
       Console.WriteLine();
       Ciphertext encryptedValue = new Ciphertext();
       encrypt.Encrypt(plainValue, encryptedValue);

       Console.WriteLine($"- the size of the freshly encrypted
             value is: {encryptedValue.Size}");
       Console.WriteLine("- the initial noise budget of the
             encrypted value: {0} bits",
       decrypt.InvariantNoiseBudget(encryptedValue));

       Plaintext decryptedValue = new Plaintext();
       Console.Write("- the decryption of encrypted value: ");
       decrypt.Decrypt(encryptedValue, decryptedValue);
       Console.WriteLine($"0x{decryptedValue}");

       /* Compute (x² + 2).*/
       Console.WriteLine("Compute squareValuePlusTwo (x²+2).");
       Ciphertext squareValuePlusTwo = new Ciphertext();
       evaluate.Square(encryptedValue, squareValuePlusTwo);
       Plaintext plainTextTwo = new Plaintext("2");
       evaluate.AddPlainInplace(squareValuePlusTwo, plainTextTwo);

       Console.WriteLine($"- the size of squareValuePlusTwo:
           {squareValuePlusTwo.Size}");
       Console.WriteLine("- the noise budget in
           squareValuePlusTwo: {0} bits",

       decrypt.InvariantNoiseBudget(squareValuePlusTwo));

    Plaintext decryptedResult = new Plaintext();
    Console.Write("- the decryption of squareValuePlusTwo: ");
    decrypt.Decrypt(squareValuePlusTwo, decryptedResult);
    Console.WriteLine($"0x{decryptedResult}");

    /*Compute (x + 1)².*/
    Console.WriteLine("Compute valuePlusOneSquare ((x+1)²).");
    Plaintext plainTextOne = new Plaintext("1");
    Ciphertext valuePlusOneSquare = new Ciphertext();
    evaluate.AddPlain(encryptedValue, plainTextOne,
         valuePlusOneSquare);
    evaluate.SquareInplace(valuePlusOneSquare);
    Console.WriteLine($"- the size of valuePlusOneSquare:
         {valuePlusOneSquare.Size}");
    Console.WriteLine("- the noise budget in
         valuePlusOneSquare: {0} bits",

    decrypt.InvariantNoiseBudget(valuePlusOneSquare));
    Console.Write("- decryption of valuePlusOneSquare: ");
    decrypt.Decrypt(valuePlusOneSquare, decryptedResult);
    Console.WriteLine($"0x{decryptedResult}");

    /* Multiply (x² + 2) * (x + 1)² * 3\. */

    Console.WriteLine("Compute encryptedOutcome
      3(+ 2)(x + 1)² .");
    Ciphertext encryptedOutcome = new Ciphertext();
    Plaintext plainTextThree = new Plaintext("3");
    evaluate.MultiplyPlainInplace(squareValuePlusTwo,
        plainTextThree);
    evaluate.Multiply(squareValuePlusTwo, valuePlusOneSquare,
         encryptedOutcome);
    Console.WriteLine($"- size of encryptedOutcome:
             {encryptedOutcome.Size}");
    Console.WriteLine("- the noise budget in encryptedOutcome:
          {0} bits", decrypt.InvariantNoiseBudget(encryptedOutcome));
    decrypt.Decrypt(encryptedOutcome, decryptedResult);
    Console.WriteLine("- decryption of 3(+2)(x+1)² =
             0x{0}", decryptedResult);
      }
}

Listing 13-14The Entire Code

整个输出如图 13-6 所示。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 13-6

全部输出

这个多项式求值代表了如何使用海豹突击队库的一个简单例子。当然,在实际应用中,您将需要处理更复杂的函数或算法。甚至这个简单的例子也可以通过使用重新线性化技术进行显著优化,该技术将加密文本的大小重置为初始值 2。简而言之,应该在每次乘法之后应用重新线性化。这种技术在海豹突击队库中可用,它在RelinearizeInplace下的Evaluator类中实现,它有两个参数:需要重新线性化的加密文本和重新线性化密钥。上述示例可以修改如下:首先,定义重新线性化关键字:

RelinKeys relinearizationKeys = keyGenerator.RelinKeys();

然后,在每次乘法之后,进行重新线性化。例如,重新线性化squareValuePlusTwo变量:

evaluate.RelinearizeInplace(squareValuePlusTwo, relinearizationKeys);

请注意,您需要重新线性化valuePlusOneSquareencryptedOutcome变量,以实现最大优化。

正如您在这个简单的例子中看到的,SEAL库非常强大,一个很大的优点是它独立于其他外部库。当应用处理整数的精确值时,在SEAL库中实现的BFV加密方案非常棒。如果应用需要处理实数或复数,那么CKKS加密方案是最好的选择,它也在SEAL库中实现。

结论

在本章中:

  • 您已经了解了什么是同态加密以及同态加密的类型。

  • 您对全同态加密有了更深入的了解,并且看到了它如此重要的原因。

  • 在一个简单的例子中,您使用了微软的SEAL库,它实现了BFV加密方案,并进行多项式求值。

文献学

  1. 阿迪·萨莫尔·罗纳德·L·李维斯特和伦纳德·阿德曼,“获取数字签名和公钥密码系统的方法”《化学文摘》第 21.2 节的来文(1978 年):第 120-126 页。

  2. 沙菲·戈德瓦瑟和希尔维奥·米卡利,“概率加密和如何玩心理扑克保密所有部分信息。”第十四届美国计算机学会计算理论年会会议录。1982.

  3. 基于离散对数的公钥密码系统和签名方案。信息理论汇刊 31.4 (1985): 469-472。

  4. Dan Boneh、Eu-Jin Goh 和 Kobbi Nissim,“评估密文上的 2-DNF 公式”密码学理论会议。施普林格,柏林,海德堡,2005。

  5. B.巴拉克和 z .布拉克斯基。《密码学的瑞士军刀》, http://windowsontheory.org/2012/05/01/the-swiss-army-knife-of-cryptography/ ,2012 年。

  6. 使用理想格的全同态加密。第 41 届美国计算机学会计算理论年会会议录。2009.

  7. Marten Van Dijk 等人,“整数上的全同态加密”密码技术理论与应用国际年会。施普林格,柏林,海德堡,2010。

  8. Zvika Brakerski 和 Vinod Vaikuntanathan,“来自(标准)LWE 的高效全同态加密”SIAM 计算期刊 43.2 (2014): 831-871。

  9. Craig Gentry、Z. Brakerski 和 V. Vaikuntanathan,“无引导的全同态加密”安全 111.111 (2011): 1-12。

  10. Craig Gentry,Amit Sahai 和 Brent Waters,“从错误中学习的同态加密:概念上更简单,渐近更快,基于属性”年度密码学会议。施普林格,柏林,海德堡,2013。

  11. 范俊峰和弗雷德里克·维考特伦,“有点实用的全同态加密”IACR 密码学 ePrint 档案 2012 (2012): 144。

  12. Jung Hee Cheon 等人,“近似值算术的同态加密”密码学与信息安全理论及应用国际会议。施普林格,查姆,2017。

  13. 陈皓、金·莱恩和瑞秋·普莱耶,“简单加密算法库-海豹突击队 2.1 版”,金融加密和数据安全国际会议。施普林格,查姆,2017。

  14. Kim Laine,《简单加密算法库 2.3》。1."微软研究院, www.microsoft.com/en-us/research/uploads/prod/2017/11/sealmanual-2-3-1.pdf (2017)。

  15. 微软海豹突击队, www.microsoft.com/en-us/research/project/microsoft-seal/

  16. 微软/海豹突击队, https://github.com/Microsoft/SEAL

  17. 对小秘密 LWE 的双重格攻击和在赫里布和海豹突击队的参数选择密码技术理论与应用国际年会。施普林格,查姆,2017。

https://en.wikipedia.org/wiki/Cyclotomic_polynomial

**

十四、带错误的环学习密码术

在这一章中,我们将讨论带错误的环学习密码术(RLWE ),它是开发专业和复杂的应用和系统的最强大和最具挑战性的方法之一。

2005 年,Oded Regev 引入了带错误的学习(LWE) [4 ]问题,它被证明是密码学未来的一个惊人的通用基础,并提供了复杂的密码构造。如果你想了解更多关于 LWE 和相关问题的信息,我们列出了一些关于基于格的密码学的最佳调查 [5 、 6 、 7 、 8 ]。

LWE 代表一个计算问题,其主要目的是用作新的密码算法的基础,并构建新的、实用的密码构造。一个例子是 NewHope [9 ,一种后量子密钥封装。NewHope 旨在提供针对量子计算机发起的密码分析攻击的保护,同时也是同态加密的基础。

R-LWE 代表了基于有限域上的特殊多项式环的更大的 LWE 问题。基于即使使用量子计算机也难以解决 RLWE 问题的假设,RLWE 密码被视为未来公钥密码的根本基础(见图 14-2 和清单 14-2 的示例)。

RLWE 密码术相对于 LWE 的重要优势在于公钥和私钥的大小。RLWE 生成的密钥代表从 LWE 获得的密钥的平方根。为了便于讨论,让我们考虑下面的例子:我们使用 128 位的安全级别,RLWE 加密算法将使用 7000 位的公钥。

有三类 RLWE 加密算法:

  • 密钥交换(RLWE-柯):2011 年,丁金泰在辛辛那提大学提出了和进行密钥交换的设想。他的基本思想 [10 诞生于矩阵乘法的结合律。这种情况下的错误用于提供安全性。论文发表于 2012 年,专利填写于同年。2014 年,Chris Peikert 根据丁的想法 [11 ]推出了一个关键运输方案。

  • RLWE 签名(RLWE-S):2011 年,柳巴舍夫斯基提出了格非、菲亚特、沙米尔 [12 ]提出的身份认证协议的改进版本,将其转换为数字签名 [13 ]。2012 年,GLP (Gunesyu,Lyubashevsky 和 Popplemann)延长了签名。

  • RLWE 同态加密(RLWE-何):同态加密的主要目标是允许对敏感数据进行计算。2011 年,Brakeersky 和 Vaikuntanathan 提出了一个使用 RLWE 的全同态加密方案,并使用密钥相关消息实现安全性 [15 ]。

在接下来的部分中,我们将通过一个简短的数学背景来展示在进一步实现之前你所知道的最基本的必要理论信息。

数学背景

带着错误学习

随着量子计算机的发展,许多现有的公钥密码系统将很容易被破解。所以抗量子计算机的加密方案有必要的硬度假设。其中一种方法是带着错误学习。通俗地说,LWE 问题是基于发现解决以下等式的值的难度:

)

在上面的等式中, ab 是公钥, s 代表密钥, e 代表误差值(或噪声)。

LWE 问题在密码学的许多领域都有应用。例如,它用于使公钥加密安全地抵御选择明文攻击或选择密文攻击、不经意传输、基于身份的加密和完全同态加密。

在论文 [1 ]中,上面的等式应用于线性方程组,变成b=A×s+e,其中(1) A 是二维矩阵,如果 s 是一维矩阵或(2)

*使用 LWE 的简单加密方案可以定义如下,考虑质数 p :

  • 密钥生成:随机选择一个向量),选择一个矩阵 A ,其中 m 行代表来自均匀分布的 m 个独立向量,从 上定义的误差分布中随机选择向量e=(e1,…emb = 计算为 + e 。公钥是对( Ab ),私钥是 s

  • 加密:给定矩阵、 Ab 以及需要加密的消息 m ∈ {0,1},对 Ab 进行随机采样,得到vA=∈AI m 的加密是一对( uv )。

  • 解密:计算值val=vb——SVA(mod p)。如果),则消息为m= 0;否则,消息是 m = 1。

上面的例子只是一个非常简单的加密方案,用来演示 LWE 问题是如何工作的。基于 LWE 问题的重要公钥加密方案是 Regev [2 ]和林德纳-佩克特加密方案。

有两种类型的 LWE 问题:LWE 搜索和 LWE 决策。在下文中,我们提供了 LWE 问题的这些变体的正式定义:

定义 LWE 搜索。给定定义在整数集合 上的值 mnp 和分布 χ sχ e ,选择)和)并计算)的值 s〉+eImod p,其中 i = 1,…, m带错误学习搜索变量问题的元组( nmpχ * s χ e * )在于确定 *s *

注意,在上面的定义中, s 是具有 n 值的列向量, a i 是具有来自 pn 值的行向量, b 是具有来自 m 元素的列向量

**LWE 决定的定义。**给定整数集合 上定义的值 np 和分布 χ sχ e ,选择)并建立两个预言如下:

  • );输出( a ,〈 as 〉 + e mod p )

  • );输出( au )

带错误学习决策代表元组( npχ sχ e )的一个变体问题,其目的是区分)和 U

带错误的环形学习

LWE 问题可以应用于系数来自有限域的多项式环。在这种情况下,LWE 问题被称为带错误的环学习 (RLWE)。在密码学中,RLWE 用于密钥交换、签名或同态加密等主题。原理类似于简单 LWE 的原理,在第一等式中 abse 都是多项式。LWE 问题的两种变体变成了

定义(RLWE 搜索)。给定值 npwithn= 2k,设 R外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传以及分布χsχ * e * eχe外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传并计算 b的值为 + e 。 带错误的环学习搜索元组的变体问题( npχ * s χ e * )在于确定 s 知道(

注意,在上面的定义中,)。

**定义(RLWE 决定)。**给定值 np + 以及环上定义的分布 χ sχerp,选择 s

  • );输出( a + e )

  • );输出( au )

元组( npχ sχ e )的环学习带错误决策变式问题是为了区分)和 U

为了使基于®LWE 的加密方案安全,需要任何多项式时间算法)(称为攻击者)解决®LWE 问题的优势是可忽略的函数。

实际实施

LWE 代表了一种量子加密的健壮方法。当您决定转向 LWE 的实用方面,实现一个处理 LWEs 的简单方法时,您需要记住,您需要创建一个密钥值( sk )和另一个值( random _ value )。下一步非常简单,因为您将需要一组值(setofvalues[])并在稍后计算p[]=t[] × sk + e.p []和setofvalues[])将成为公钥。

我们将展示的第一个例子(见图 14-1 )代表了 Oded Regev 在 [4 ]中定义的一种加密方法,称为带错误学习。算法的工作流程很简单:消息(见图 14-1 第一行)的每一位都是按照 Oded Regev from4 的方案加密的。代码如清单 14-1 所示。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 14-1

Oded Regev 使用的加密方法

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace LWECase1
{
    class Program
    {
        public static int[] public_key = new int[200];
        public static int[] values = new int[]
                                 { 5, 8, 12, 16, 2, 6, 11, 3, 7, 10 };
        public static int s = 5;
        public static int e = 12;
        public static int message = 1;
        public static int val = 0;
        public static int sum = 0;
        public static int remainder = 0;

        static void Main(string[] args)
        {
            Random randValue = new Random();
            int[] res = new int[200];
            int k = 0;

            //**
            for (int x=0; x<values.Length; x++)
            {
                public_key[k] = values[x] * s + e;
                k++;
            }

            for(int i=0; i< public_key.Length; i++)
            {
                res[i] = randValue.Next(public_key[i],
                                    public_key.Length / 2);
            }

            for(int j=0; j<res.Length; j++)
            {
                sum += res[j];
            }

            Console.WriteLine("The message to be send: {0}", message);
            Console.WriteLine("The random values:");
            PrintValues(values);
            Console.WriteLine("The public key is: ");
            PrintValues(public_key);
            Console.WriteLine("The selected values are:");
            PrintValues(res);

            //** compute the sum
            if (message == 1)
                sum += 1;

            Console.WriteLine("The sum is: {0}", sum);

            Console.WriteLine("The encrypted message is: {0}", sum);
           //** compute the remainder
            remainder = sum % s;

            if(remainder % 2 == 0)
                Console.WriteLine("The message received is 0");
            else
                Console.WriteLine("The message received is 1");

            Console.ReadKey();
        }

        //** dealing with arrays
        public static void PrintValues(Object[] myArr)
        {
            foreach (Object i in myArr)
            {
                Console.Write("\t{0}", i);
            }
            Console.WriteLine();
        }

        //** dealing with arrays
        public static void PrintValues(int[] myArr)
        {
            foreach (int i in myArr)
            {
                Console.Write("\t{0}", i);
            }
            Console.WriteLine();
        }
    }
}

Listing 14-1Implementation of LWE Encryption Method by Oded Regev

在清单 14-2 中,我们将提供一个基于 LWE 的公钥加密的例子。我们将从创建一个秘密值( s )开始,它将代表私钥。下一步是创建由随机数的值形成的公钥( A )。我们将根据 As 和随机误差 e 生成另一组数字( B )。这个例子是针对单个位完成的,与清单 14-1 中的前一个例子一样。

这个例子的简单工作流程是

  • Between 0 and 100, we will select a random set of 20 values which represent the public key (A). Let’s assume that those 20 values are

    )

  • Next, we will define a list (B) and each element will be as Bi = Ai × s + ei(mod q), where s represents the secret key and e represents a list of small random values, called the errors values. As an example of the statement made, let’s consider a prime number (q) equal with 97, and the error vector (eas

    )

  • A and B lists are considered the public key and s represents the secret key. At this point, we are able to distribute A and B to everybody who wishes to proceed with an encryption of a message (with the condition to keep s secret). In order to proceed with the encryption, we need to use the samples from A and B. Moving forward, based on those sample we take a bit from the message (M) and compute the following two values:

    )

)

  • At this point, we say that the encrypted message is (u, v). To proceed with the decryption, we need to compute

    )

  • 如果)消息等于 0,否则为 1。

上面描述的程序是从 Oded Regev 的论文 [5 ]中总结出来的,以便于理解和清楚地理解如何在现实中转换 LWE 的复杂性。接下来,让我们看看清单 14-2 ,看看这个实现会是什么样子。输出如图 14-2 所示。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 14-2

使用 LWE 输出公钥加密的例子

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace PublicKeyEncLWE_Case2
{
    class Program
    {
        public static int[] A = new int[30];
        public static int[] B = new int[30];
        public static int[] e = new int[30];
        public static int s = 20;
        public static int message = 1;
        public static int q = 15;
        public static int nvals = 20;

        static void Main(string[] args)
        {
            Random randomSample = new Random();
            IEnumerable<int> q_values = Enumerable.
                                      Range(0, q);
            IEnumerable<int> n_values = Enumerable.Range(
                                     nvals - 1, nvals / 4);
            double u = 0;
            double v = 0;
            int sample = 0;

            foreach (int q_value in q_values)
            {
                for (int i = 0; i < q; i++)
                {
                    A[i] = randomSample.Next(q_value, nvals);
                }
            }
            for (int x = 0; x < A.Length; x++)
            {
                e[x] = randomSample.Next(1, 4);
                B[x] = (A[x] * s + e[x]) % 2;
            }

            Console.WriteLine("PARAMETERS SECTION\n");
            Console.WriteLine("\tMessage to be send: {0}", message);
            Console.WriteLine("\tThe public key (A):");
            PrintValues(A);
            Console.WriteLine("\tThe public key (B):");
            PrintValues(B);
            Console.WriteLine("\tThe errors (e) are: ");
            PrintValues(e);
            Console.WriteLine("\tThe secret key is: {0}", s);
            Console.WriteLine("\tPrime number is: {0}", q);

            foreach(int n_value in n_values)
            {
                sample = randomSample.Next(nvals - 1, n_value);
                Console.WriteLine("The sample is {0}", sample);
            }

            IEnumerable<int> samples = Enumerable.Range(0, sample);
            string errors = string.Empty;

            for (int x = 0; x < samples.Count(); x++)
            {
                errors = "[" + A[x] + ", " + B[x] + ", ], end
                                                = " + u + A[x];
            }

            Console.WriteLine(errors);

            double flooring = q / 2;

            v += Math.Floor(flooring) * message;

            u = v % q;
            v = u % q;

            Console.WriteLine("u = {0}", u);
            Console.WriteLine("v = {0}", v);

            double res = (v - s * u) % q;
            Console.WriteLine("The result is: {0}", res);
            if (res > q / 2)
                Console.WriteLine("Message is 1");
            else
                Console.WriteLine("Message is 0");

            Console.ReadKey();
        }

        public static void PrintValues(Object[] myArr)
        {
            foreach (Object i in myArr)
            {
                Console.Write("\t{0}", i);
            }
            Console.WriteLine();
        }

        public static void PrintValues(int[] myArr)
        {
            foreach (int i in myArr)
            {
                Console.Write("\t{0}", i);
            }
            Console.WriteLine();
        }
    }
}

Listing 14-2Implementation of Public Key Encryption Example Using LWE

结论

在本章中,您使用 C# 编程语言尝试了第一种实用的带错误的环学习加密方法。它可以为专业人士提供多种挑战的空间,也是对这种加密原语做出重大贡献的起点。

在本章结束时,您现在有以下内容:

  • R-LWE 所基于的主要概念和定义的坚实但简短的数学背景,如果没有它,实际实现将有许多空白需要填补

  • 体验 RLWE 的数学概念及其在实践中的转换带来的挑战

文献学

  1. Oded Regev,《学习与错误问题》, https://cims.nyu.edu/~regev/papers/lwesurvey.pdf

  2. O.格子上,错误学习,随机线性码和密码术。在*《美国计算机学会杂志(JACM)】*,第 56 卷第 6 期,第 1-40 页。2009.

  3. R.林德纳和 c .佩克特,“基于 LWE 的加密的更好的密钥大小(和攻击)”在RSA 会议上的密码学家跟踪(第 319-339 页)。斯普林格,柏林,海德堡。2011.

  4. O.Regev,“带错误的学习问题(邀请调查)”,载于 2010 IEEE 第 25 届计算复杂性年会(第 191-204 页)。马萨诸塞州剑桥市 doi: 10.1109/CCC.2010.26. 2010。

  5. D.Micciancio 和 O. Regev,“基于格的密码学”在 D. J. Bernstein 和 J. Buchmann (eds),后量子密码术。斯普林格,2008 年。

  6. C.佩克特。“基于格的密码学的一些最新进展。”TCC’09,2009 特邀教程幻灯片。

  7. D.米西安西奥。“最坏情况复杂性假设的加密函数。”载于:P. Q. Nguyen 和 b . Vall ee(编辑),《LLL 算法:调查和应用,信息安全和密码学》,第 427-452 页。斯普林格,2008 年。预赛。LLL25 版本,2007。

  8. O.雷格夫。"基于格的密码术。"In CRYPTO (第 131–141 页)。2006.

  9. 新希望——后量子密钥封装。网上有: https://newhopecrypto.org/

  10. 丁金泰,谢翔和林小东,“一个简单的基于错误学习问题的可证明安全的密钥交换方案”在线可用: https://eprint.iacr.org/2012/688 2012 年。

  11. C.Peikert,“互联网的格子密码术”在 M. Mosca (ed) 后量子密码术中。PQCrypto 2014。计算机科学讲义,第 8772 卷。施普林格,查姆。2014.

  12. Y.“菲亚特-沙米尔识别协议和格非-菲亚特-沙米尔签名方案”在 H.C.A. van Tilborg 和 S. Jajodia(编辑)的《密码学与安全百科全书。马萨诸塞州波士顿斯普林格。2011.

  13. 动词 (verb 的缩写)柳巴舍夫斯基,“没有陷门的格子签名”在 D. Pointcheval 和 T. Johansson (eds )的《密码学进展——EUROCRYPT 2012》中。欧洲密码 2012。计算机科学讲义,第 7237 卷。斯普林格,柏林,海德堡。2012.

  14. Tim Güneysu、Vadim Lyubashevsky 和 Thomas Pö ppelmann,“实用的基于格的加密:嵌入式系统的签名方案”在伊曼纽尔普鲁夫和帕特里克绍蒙特(编辑。)计算机科学讲义,(第 530–547 页)。斯普林格·柏林·海德堡。doi:10.1007/978-3-642-33027-8 _ 31。国际标准书号 978-3-642-33026-1。2012.

  15. 兹维卡·布拉克斯基和维诺德·维昆塔纳森,“来自环 LWE 的全同态加密和密钥相关消息的安全性”在菲利普·罗加威(编辑。)计算机科学讲义(第 505–524 页)。斯普林格·柏林·海德堡。doi:10.1007/978-3-642-22792-9 _ 29。国际标准书号 978-3-642-22791-2。2011.*

十五、基于混沌的密码学

基于混沌的密码学是应用混沌理论及其数学背景来创造新的独特的密码算法。1989 年,罗伯特·马修斯在 [1 ]首次对其进行了研究,并引起了人们极大的兴趣。

与我们每天使用的普通密码原语相比,为了以有效的方式使用混沌理论和系统,混沌映射必须在考虑混淆和扩散的情况下实现。在本章中,我们将使用混沌系统的概念来指代加密算法。

为了理解混沌系统和密码算法之间的区别和相似之处,让我们来看看表 15-1 中所示的以下关系,这些关系是由 L. Kocarev 在 [2 中建立的。

表 15-1

混沌系统与密码算法的异同

|

Chaotic System

|

Cryptographic Algorithm

|
| — | — |
| Phase space: subset of real numbers | Phase space: finite set of integers |
| Iterations | Rounds |
| Parameters | Key |
| Sensitivity to a change in initial conditions and parameters | Diffusion |
| ? | Security and performance |

为了展示表 16-1 中所示的相似性和差异,我们将把换挡图 :

)

作为一个混沌系统的例子来考虑

其中相空间x=【0,1】表示单位区间, a > 1 表示整数。

不同的函数和离散时间系统已被提出用于密码学。一旦你看了它们,你会看到相空间代表一个有限的整数集合,参数等于整数。一个最常见的例子是由上面作为例子给出的移位映射的离散相空间版本表示:

)

其中 a > 1、 Np 表示整数,p∈【0,1,…、N—1】。如果 Na 互质,则换挡图的第二表示是可逆的。这意味着有限相空间动力系统内的所有轨迹都被特征为周期性的。在这种情况下,您可以看到正在引入的新概念,周期函数 P N 将特征图 F 的最小周期,即)为其单位, P * N * 表示最小值,为系统大小 N 的函数。

当处理实际的混沌系统时,另一个非常重要的度量是由李亚普诺夫指数来特征的,它通常等于 0。这是因为轨道是周期性的,它会重复自己。

也就是说,我们将给出两个框图(文本加密和图像加密)来展示使用混沌方法的加密方案是什么样子。在图 15-1 和图 15-2 中,可以看到使用 logistic 映射对一个明文进行加密和解密的过程。对于图像加密和解密,图 15-3 给出了一个示例模型。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 15-3

图像加密密码系统框图 [15

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 15-2

使用逻辑映射 [14 ]进行文本加密的框图

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 15-1

使用逻辑映射 [14 ]进行文本加密的框图

基于作为示例提出的框图,您可以查看原始论文和本章末尾列出的其他论文,并看到加密模型和构建它们可以根据所使用的混沌映射而有所不同。在开始设计新的方法和混沌加密机制之前,理解特定的混沌映射是如何工作的是非常重要的。使用以下框图作为从理论到实践的实践指南是一个很好的起点,因为模型的创建考虑了表 15-1 中列出的相似性和差异性。

证券分析

本节将把安全分析称为发现密码系统的弱点和安全漏洞、获得全部或部分加密图像/明文或在不知道算法或解密密钥的情况下找到密钥的方法。

在 [3 和 [4 中可以找到一些有趣的对加密图像的攻击。当设计混沌系统或进行密码分析攻击时,考虑以下标准和分析是很重要的:

  • 关键空间分析。该分析处理寻找解密密钥的尝试次数。这是通过在密码系统的密钥空间内尝试所有可能的密钥来实现的。值得注意的是,密钥空间随着密钥大小的增加而呈指数增长。

  • 关键敏感度分析。为了有一个好的图像加密系统,密钥的敏感性是重要的,需要加以考虑。如果密钥中只有一位被更改,这将输出完全不同的图像(加密或解密)。

  • 统计分析。执行这种类型的分析的目的是证明真实图像和加密图像之间的关系。

  • 相关系数分析。直方图是一种重要的图形工具,用于研究由动态系统的轨迹产生的值的分布。除了直方图分析之外,用于研究普通图像和/或加密图像的相邻像素的相关性的另一个重要工具是基于垂直、水平和对角分布的两个像素的相关性。

  • 信息熵分析。熵分析用于测试加密算法的鲁棒性。比较普通图像和加密图像的熵是非常重要的。通过这样做,我们能够看到加密图像的熵大约等于 8 位深度。这将有助于我们证明对抗熵攻击的加密技术。

  • 微分分析。在差分分析的帮助下,我们将确定加密算法对算法中产生的任何微小变化的敏感性。有两个标准用于测试灵敏度。一个是 NPCR(像素数变化率),第二个是 UACI(统一平均变化强度)。一旦计算出这两个标准,基于高值,我们可以看到在普通图像中发生的任何微小变化的迹象,这将在加密图像中产生显著变化。

用于明文和图像加密的混沌映射

在这一节中,我们将介绍基于加密目标(文本加密或图像加密)的混沌映射。

如上所述,表 15-2 中列出的大多数图像加密算法都由参考文献中提到的作者使用不同的安全性分析进行了测试。对性能进行验证和对密码系统的健壮性进行评估是非常有用的。根据他们的分析和测试,所有的参考文献都被检查和选择为好的参考文献。

表 15-2

用于图像加密的混沌映射(系统)

|

混沌映射(系统)

|

韵律学

|

钥匙

|

文献学

|
| — | — | — | — |
|

|

NPCR(美国国家广播公司)

|

阿兵哥

|

空间

|

敏感性

|
| — | — | — | — | — |
| 罗伦兹面包师 | 7.9973 | - | - | 2 128 | 高的 | [5 |
| 罗伦兹 | - | - | - | 大型 | 中等 | [6 |
| 海农 地图 | 7.9904 | 0.0015% | 0.0005% | 2 128 | 高的 | [7 |
| 物流地图 | 7.9996 | 99.6231% | 33.4070% | 10 45 | 高的 | [8 |
| 三角地图 | - | 0.25% | 0.19% | 2 302 | - | [9 |
| 阿诺德 cat map | 7.9981 | 99.62% | 33.19% | 2 148 | 高的 | [10 |
| 切比雪夫地图 | 7.9902 | 99.609% | 33.464% | 2 167 | 高的 | [11 |
| 圆形地图 | 7.9902 | 99.63% | 33% | 2 256 | 高的 | [12 |
| 阿诺德地图 | - | 0.0015% | 0.004% | - | - | [13 |

实际实施

混沌系统的大部分应用可以在明文加密图像加密上看到。正如我们在本书中讨论的其他密码学领域一样,研究团体提供了大量的理论贡献。实际实施的缺乏给研究人员和专业人员带来了多重困难和挑战。

混沌系统加密的实际实现并不多,但是在 [16 ]中可以找到一些实用的方法(这里我们指的是伪代码算法)。该工作有一个非常深入的结构,并给出了一些关于如何通过提供伪代码来实现基于混沌理论的不同密码系统的想法。这项工作涵盖以下密码系统类型:

  • 基于混沌的公钥密码

  • 密码学中的伪随机数生成

  • 高维混沌映射的形成及其在密码学中的应用

  • 基于混沌的哈希函数

  • 基于混沌的视频加密算法

  • 混沌密码的密码分析

  • 基于混沌的密码的硬件实现

  • 混沌保密光通信系统的硬件实现

在 [16 ]中,从第二章开始,作者提出了一个有趣的公钥密码系统,它使用混沌方法,由三个步骤组成:密钥生成算法(见伪代码 15-1)、加密算法(见伪代码 15-2)和解密算法(见伪代码 15-3)。该场景是两个用户实体 Alice 和 Bob 之间的典型通信。让我们看看每个算法的结构,最后我们将提供一个简单的定向实现,作为专业人员未来的参考指南。

*伪代码 15-1。*16

**** 必须生成一个大整数 a

  • 根据选择为p∈[1,1]的随机数,计算Ga(p)。

  • 爱丽丝将她的公钥设为( pG ( p )),私钥设为 a

Start. Alice will need, before the communication, to generate the keys. For this, she will accomplish the following:

*伪代码 15-2。*16

**** 获取爱丽丝的可信公钥( pGa(p))。

  • 计算并将消息表示为数字M∈[1,1]。

  • 生成一个大整数 r

  • 计算*【r】(),【g9】【r】***

*** 取密文作为C=(Gr(p), X )发给爱丽丝。**

Start. Bob wants to encrypt a messsage. To achieve this, the following must be done:

伪代码 15-3。 解密算法16

*** 爱丽丝要用她的私钥 a 并计算Gat=Ga(Gr(p)。

  • 通过计算)获得消息 M
Start. Alice wants to read the text and to do this she will have to recover M from the ciphertext C. To achieve this, the following steps are done:

基于上面列出的算法,我们将移动到一个实际的实现作为例子。清单 15-1 展示了基于二维环面的自同构的加密和解密。应用有三个类:类TorusAutomorphism(见清单 15-1 )、类GenerateChaosValues(见清单 15-2 )和主Program类(见清单 15-3 )。该应用已经按照上面的伪代码清单进行了相应的修改。您可以在图 15-4 中看到输出。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 15-4

混沌环面自同构的输出

每个类都有其用途,如下所示:

  • TorusAutomorphism类:该类包含处理整个字符串的char encryption (object CharacterEncryption), char decryption (object CharacterDecryption)main encryption (object[] Encryption)decryption (object[] Decryption)函数的函数和方法。

  • 类:这个类处理自同构的结构函数,比如旋转操作和设置元素的索引。

  • 类:类代表应用的主入口点。

using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ChaosSystemCryptography
{
    class Program
    {
        public static void Main(string[] args)
        {
            bool logging = true;
            string key = "$6G";
            string input_value = string.Empty;
            Console.Write("What to you want to do? Encryption
                                          (e) or Decryption (d): ");
            string option = (Console.ReadLine() == "encrypt")
                                                    ? "e" : "d";

            int zero_location = Convert.ToInt32(key[0]);
            int one_location = Convert.ToInt32(key[1]);
            int two_location = Convert.ToInt32(key[2]);

            TorusAutomorphism torus_automorphism = new
                                         TorusAutomorphism();

            GenerateChaosValues generator0 = new
                        GenerateChaosValues((logging == true) ?
                        "generator0" : null);
            GenerateChaosValues generator1 = new
                        GenerateChaosValues((logging == true) ?
                        "generator1" : null);
            GenerateChaosValues generator2 = new
                        GenerateChaosValues((logging == true) ?
                        "generator2" : null);
            GenerateChaosValues[] generators = new
                        GenerateChaosValues[] { generator0,
                        generator1, generator2 };

            generator0.GeneratorRotation(zero_location);
            generator1.GeneratorRotation(one_location);
            generator2.GeneratorRotation(two_location);

            if (option == "e")

            {
                Console.Write("Enter the text for
                                              encryption: ");
                input_value = Console.ReadLine();

                if (logging == true)
                {
                    generator0.PrintInConsole(zero_location);
                    generator1.PrintInConsole(one_location);
                    generator2.PrintInConsole(two_location);
                }

                Console.WriteLine("");
                Console.WriteLine($"The input message:
                                          {input_value}");

                object[] finalValue =
                            torus_automorphism.Encryption(
                                input_value, generators, logging);

                Console.WriteLine("");
                Console.Write("\nThe output message: ");
                for (int j = 0; j < finalValue.Length; j++) {
                           Console.Write($"{finalValue[j]}"); }
            }
            else if (option == "d")
            {
                Console.Write("What is the ciphertext for
                                                decryption: ");
                string ciphertext_input = Console.ReadLine();
                if (logging == true)

                {
                    generator0.PrintInConsole(zero_location);
                    generator1.PrintInConsole(one_location);
                    generator2.PrintInConsole(two_location);
                }
                Console.WriteLine($"\nEncryption for input
                                      string: {ciphertext_input}");
                     object[] finalDecrypted =
                          torus_automorphism.Decryption(ciphertext
                            _input, generators, logging);
                Console.Write("\nThe decrypted text is: ");
                for (int j = 0; j < finalDecrypted.Length;
                                                          j++)
                       { Console.Write(finalDecrypted[j]); }
            }
            Console.WriteLine("\n Press any key to exit...");
            Console.ReadKey();
        }
    }
}

Listing 15-3Main Program

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ChaosSystemCryptography
{
    class GenerateChaosValues
    {
        private object[] items = new object[94];
        private char last_direction;
        private readonly string generator_ID;

        //** the property will return the index of the item
        //** for a specific value as character
        public int ItemIndex(char inputValue)
        {
            int locationElement;
            locationElement = Array.IndexOf(items,
                                        inputValue);
            return locationElement;
        }

        //** the property will return the index of the item
        //** for a specific value as integer
        public object ItemIndex(int inputValue)
        {
            object locationElement;
            locationElement = items.GetValue(inputValue);
            return locationElement;
        }

        //** constructor
        public GenerateChaosValues(
                        string generator_name = null)
        {
            generator_ID = generator_name;
            for (int i = 32; i <= 125; i++)
            {
                items[i - 32] = (char)i;
            }

        }

        public void GeneratorRotation(int rotation,
                                          char chosen_direction)
        {
            object[] rotation_done = new object[items.Length];
            int length = items.Length;
            int rotation_location = (rotation % length);

            //** the torus will have a right rotation
            if (chosen_direction == 'R')
            {
                for (int in_direction = 0; in_direction <
                                     length; in_direction++)
                {
                    if (rotation_location + in_direction
                                      >= length)
                    {
                        int suplimentary_rotation =
                             rotation_location - (length –
                                               in_direction);
                        rotation_done[suplimentary_rotation] =
                                           items[in_direction];
                    }
                    else
                    {
                        rotation_done[in_direction +
                                    rotation_location] =
                                   items[in_direction];
                    }
                }
                last_direction = 'R';
            }

            else
            {
                for (int in_direction = 0; in_direction <
                                        length; in_direction++)
                {
                    if (rotation_location + in_direction
                                         >= length)
                    {
                        int suplimentary_rotation =
                                  rotation_location - (length –
                                      in_direction);
                        rotation_done[in_direction] =
                                 items[suplimentary_rotation];
                    }
                    else
                    {
                        rotation_done[in_direction] =
                               items[in_direction +
                               rotation_location];
                    }
                }
                last_direction = 'L';
            }
            Array.Copy(rotation_done, items,
                             rotation_done.Length);

        }
        public void GeneratorRotation(int rotation)
        {
            object[] rotation_done = new object[items.Length];
            int length = items.Length;
            int rotation_location = (rotation % length);

            for (int in_direction = 0; in_direction < length;
                                              in_direction++)
            {
                if (rotation_location + in_direction
                                              >= length)
                {
                    int suplimentary_rotation =
                          rotation_location –
                                (length - in_direction);
                    rotation_done[suplimentary_rotation] =
                                        items[in_direction];
                }

                else
                {
                    rotation_done[in_direction +
                              rotation_location] =
                              items[in_direction];
                }
            }
            last_direction = 'R';
            Array.Copy(rotation_done, items,
                              rotation_done.Length);
        }
        public void PrintInConsole(int rotated = 0)
        {
            Console.Write($"{generator_ID} rotated {rotated}
            {((last_direction == 'L') ? "left" : "right")}: ");
            for (int i = 0; i < items.Length; i++)
            {
                Console.Write($"{items[i]}, ");
            }
            Console.WriteLine("");
        }
    }
}

Listing 15-2Generating Chaotic Values for Torus

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ChaosSystemCryptography
{
    class TorusAutomorphism
    {
        private object CharacterEncryption(char
                  input_characters, GenerateChaosValues[]
                  iterations, int generators, bool logging)
        {
            int spotted_difference;
            spotted_difference = iterations[(generators % 2 ==
                   0) ? 0 : 1].ItemIndex(input_characters);
            foreach (GenerateChaosValues iteration_generator
                                              in iterations)
            {
               iteration_generator.GeneratorRotation(
                             spotted_difference, 'L');
                if (logging == true) {
                       iteration_generator.PrintInConsole(
                            spotted_difference + generators); }
            }
            return iterations[2].ItemIndex(0);
        }

        public object[] Encryption(string input_locations,
                        GenerateChaosValues[]
                        generators_locations, bool logging)
        {
            object[] finalOutputObject = new
                             object[input_locations.Length];
            for (int i = 0; i < input_locations.Length; i++)
            {
                finalOutputObject[i] =
                        CharacterEncryption(input_locations[i],
                        generators_locations, i, logging);
            }
            return finalOutputObject;
        }

        private object CharacterDecryption(char
                        input_characterst, GenerateChaosValues[]
                        iterations, int generators, bool
                        logging)
        {
            int spotted_difference;
            spotted_difference =
                   iterations[2].ItemIndex(input_characterst);
            foreach (GenerateChaosValues
                   iteration_generator in iterations)
            {
                   iteration_generator.GeneratorRotation(
                        spotted_difference, 'L');
                if (logging == true) {
                    iteration_generator.PrintInConsole(
                        spotted_difference + generators); }
            }
            return iterations[(generators % 2 == 0) ?
                              0 : 1].ItemIndex(0);
        }

        public object[] Decryption(string
                              encryption_locations,
                              GenerateChaosValues[]
                              generators_locations, bool logging)
        {
            object[] finalOutputObject = new
                       object[encryption_locations.Length];
            for (int i = encryption_locations.Length - 1;
                                              i >= 0; i--)
            {
                finalOutputObject[i] =
                     CharacterDecryption(encryption_locations[i],
                            generators_locations, i, logging);
            }
            return finalOutputObject;
        }
    }
}

Listing 15-1Chaos Encryption/Decryption

Using Torus Automorphism

结论

在这一章中,我们讨论了一种有趣的加密方法,基于混沌的加密。新的密码算法正在使用混沌映射以不同于过去使用的方式生成新的密码原语。

在本章结束时,您现在已经了解了以下内容:

  • 基于混沌的密码原语是如何构建的,以及它们与普通密码原语的不同之处

  • 混沌系统如何设计用于文本加密和图像加密

  • 如何用混沌系统和自同构环面实现一个密码系统

文献学

  1. 罗伯特·马修斯,“关于‘混沌’加密算法的推导”,载于 Cryptologia 13 ,第 1 期(1989): 29-42 页。

  2. 长度 Kocarev,“基于混沌的密码学:概述”,IEEE 电路和系统杂志,第 1 卷,第 3 期,第 6-21 页,2001 年,doi: 10.1109/7384.963463。

  3. Ali Soleymani、Zulkarnain Md Ali 和 Md Jan 诺丁,“关于安全图像传输的主要方面的调查”,载于世界科学、工程和技术学院,2012 年第 66 期,第 247–254 页。

  4. D.Chattopadhyay、M. K. Mandal 和 D. Nandi,“使用圆映射的对称密钥混沌图像加密”,载于印度科技期刊,第 4 卷第 5 期(2011 年 5 月)ISSN: 0974- 6846,第 593-599 页。

  5. Anto Steffi 和 Dipesh Sharma,“使用混沌映射对图像进行加密和解密的改进算法”,载于*《国际科学与研究杂志(IJSR)】*,印度在线 ISSN: 2319-7064,第 2 卷第 2 期,2013 年 2 月。

  6. K.Sakthidasan Sankaran 和 B.V. Santhosh Krishna,“一种用于数字彩色图像加密和解密的新混沌算法”,载于国际信息与教育技术期刊,第 1 卷第 2 期,2011 年 6 月。

  7. Somaya Al-Maadeed、Afnan Al-Ali 和 Turki Abdalla,“一种新的基于混沌的图像加密和压缩算法”,载于电气和计算机工程杂志,2012 卷,文章 ID 179693,Hindawi 出版公司。

  8. Hazem Mohammad Al-Najjar 和 Asem Mohammad AL-Najjar,“基于逻辑映射和像素映射表的图像加密算法”

  9. 索德伊夫·阿哈德普尔和亚塞尔·萨德拉,“使用混沌耦合映象格子的基于混沌的图像加密方案”

  10. Kamlesh Gupta 和 Sanjay Silakari,“使用混沌映射进行快速彩色图像加密的新方法”,载于信息安全杂志,2011 年 2 月 139-150 日。

  11. 崇富,,,孟伟红,,杨勇,雅文,“一种基于混沌的改进扩散策略的数字图像加密方案”,美国光学学会,【2012 年 1 月 30 日,第 20 卷第 3 期,第 2363–2378 页。

  12. D.Chattopadhyay、M. K. Mandal 和 D. Nandi,“使用圆映射的对称密钥混沌图像加密”,载于印度科技期刊,第 4 卷第 5 期,2011 年 5 月,ISSN: 0974- 6846,第 593-599 页。

  13. Shima Ramesh Maniyath 和 Supriya M,“一种基于 DNA 序列的未压缩图像加密算法”,载于计算机科学&信息技术(CS & IT) ,CCSEA 2011,CS & IT 02,第 258–270 页。

  14. Miguel Murillo-Escobar,“基于逻辑映射的新型对称文本加密算法”,2014 年。

  15. K.Sakthidasan 和 B. V. Santhosh Krishna,“数字彩色图像的图像加密和解密的新协同算法”载于*《国际信息与教育技术杂志》*,第 1 卷,第 2 期,2011 年 6 月。网上有: http://www.ijiet.org/papers/23-E20098.pdf

  16. 柳普科科卡列夫和连信国。基于混沌的密码学——理论、算法和应用。斯普林格,2011 年。**********

十六、大数据加密

大数据被定义为提取、操纵和分析无法正常处理的大规模数据集(例如 TB 或 Pb 的数据)的过程。

大数据加密处理确保数据的机密性、完整性和真实性。这是一个敏感的话题,需要小心对待,因为每个业务和架构环境的计算模型都是不同的。大数据加密不同于其他加密原语,因为在访问控制策略、云基础架构和存储机制方面,概念和方案的设计方式不同。

本章将从基于云环境的通用计算模型开始,这将允许并促进基于大数据分析的应用。我们将首先根据云计算节点在大数据分析中扮演的角色对其进行分类。我们的旅程基于[3,我们将通过定义以下节点来稍微扩展符号:

  • I N 是用于正被使用的应用的原始数据的输入节点。这种节点用于前端用户输入的数据或来自读取或捕获传感器(如指纹读取器、全息签名、人脸识别等)的数据。).

  • C N计算节点,由于应用的计算过程而发挥重要作用。这种节点基于并包括摄取节点,在我们的例子中,我们称之为消费节点。他们的目标是扫描输入数据并对其进行提炼,以便为分析过程做好准备,并准备好传递给富集节点,目标是实际的分析处理*。*

  • S N存储节点,对于对数据应用加密机制非常重要。它的作用是存储在不同类别的用户或第三方之间发生的计算过程中发现的数据。理解输入数据输出数据存储在该节点内非常重要。

  • R N 是*结果节点,*处理接收正在执行的一些计算过程的输出。它能够自动决定是使用上面的输出作为基础,还是将输出发送到特定的客户端。

图 16-1 显示了基于上述概念的大数据分析云架构示例。该模型可以被视为描述基于大数据的各种应用的模式。话虽如此,我们将注意到以下一组或多组类型为 H 的节点,如下所示H+,其中H∈{INC NS N

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 16-1

具有大数据分析应用的云架构示例

在图 16-1 中,你可以看到一个通用的云模型,它是一个查询数据集的应用的例子。示例中的IN表示启动收集参考数据集过程的工具。序列数据由输入节点发送到CN(摄取)节点。这里,计算过程是针对需要被解析的序列进行的,并且在过程结束时被组织到文件或数据库中。下一步是将文件和数据库发送到SN(存储)。有时,CN(浓缩)会对存储的数据执行额外的计算。这个过程大部分时间是离线完成的,方法是根据用户的需求更新相关的元数据。在我们的示例中,RN(数据接收者)代表将数据集与参考数据集关联的用户。

云计算对于在其实体之间传输的任何敏感数据都有一定的风险。为了实现云中加密技术提供的保护,我们将从三个最重要的安全目标来考虑安全性,即 CIA(机密性、完整性和可用性):

  • 机密性:敏感数据,严格地说是指计算输入和输出,必须保持秘密,以防止不受信任的一方或其他潜在的对手。

  • 完整性:必须尽快检测出任何未经授权更新敏感数据的修改。

  • 可用性:数据所有者可以访问数据和计算资源。

让我们关注一下可用性、,因为它在当今大多数云环境中都没有任何加密手段。我们将需要在云计算的保密性和完整性以及如何存储数据上做出让步。如何部署云将决定如何实现机密性和完整性。从一开始就确定谁控制云的每个组件以及组件之间的信任度是非常重要的。基于此,我们将考虑以下场景:

  • 可信云:这种类型的云由政府部署,它与任何外部网络和对手完全隔离。用户和客户可以存储他们的文件,而不用担心它们会被破坏或被盗。这并不意味着完全隔离将提供全面保护。一些节点是暴露的,它们很容易被恶意软件或内部人员破坏。

  • 半可信云:这是一个有趣的场景,因为它是云资源的真实部署。在这种类型的云中,客户端不需要完全信任云,同时也没有指定/提到云是完全不可信的。相反,云的一些部分和组件处于控制之下,提供了在特定时间监控对手活动的解决方案。

  • 不受信任的云:数据的所有者不信任云或任何云节点。在这种情况下,我们将无法保持和提供外包给云的数据或计算的一定程度的机密性或完整性。在这种情况下,客户需要有解决方案和保护措施,以确保机密性和完整性。这种模式被分配给公共云。

在我们经历了一些基本元素以形成云计算和大数据的基础之后,可以在这种环境中应用以确保大数据基础架构中数据安全性的加密技术非常复杂,如果没有专用的第三方软件库或经验丰富的专业人员,它们的适用性很难实现。

在本章中,我们将重点介绍三种加密技术,它们特别适用于实现部署在云中的大数据应用的安全性:

  • 同形加密(HE)在第十三章中介绍。

  • 可验证计算(VC)代表了本章的第一个目标。

  • 安全多方计算(MPC)是本章的第二个目标。

还有其他加密技术可以成功应用于实现云计算的安全性,例如

  • 功能加密

  • 基于身份的加密

  • 基于属性的加密

此外,我们将专注于我们认为有前途并可应用于真实环境的技术。这并不是说 FE、IE 或 AE 等加密类型在真实环境中不具有适用性,而是此时此刻,许多作品都是基于理论假设,并且它们中的大多数是在没有考虑到商业和行业应用的要求和需求的情况下编写的。从理论到实践是一条漫长的道路,需要理论家和实践者携手同行。他们需要坐在圆桌旁,找到当今真正重要的问题的解决方案,以解决存在的问题和差距。

可验证的计算

可验证计算,或可验证计算,是一台或多台计算机将某些功能的计算量卸载给其他人(如具有不可信状态的客户端)的可能性,同时结果被连续验证。见图 16-2 。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 16-2

可验证的计算场景。云的节点没有任何完整性保护的信任级别。

VC 在真实环境中一个非常有趣的应用是 Merkle 树,目的是验证数据的完整性。对于大数据环境,Merkle 树被定义为可用于验证项目、数据、行、数据集合等不同属性的完整性的数据结构。Merkle 树的好处是它可以处理大量的数据。将可验证的计算算法与 Merkle 树结合起来,在这个方向上已经取得了进展。

在清单 16-1 中,我们将展示一个场景,其中 Merkle 树用于验证来自部署在大数据环境中的数据库的数据。这个例子只是一个模拟(见清单 16-2 和图 16-3 )。在真实的大数据环境中部署应用需要进行适当的调整。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 16-3

哈希校验完整性

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace VerifiableComputation
{
    class Program
    {
        static void Main(string[] args)
        {
            //** the following items can be seen as big data
            //** items from a database
            //** as being the result of a query
            List<string> bigdata_items = new List<string>
            {
                "WelcomeToApress!",
                "Studying C# is amazing",
                "Adding extra spice, such as cryptography
                   makes it so challenging!",
                "You can master it with passion and
                 dedication!",
                "Good luck!"
            };

            MerkleTreeImplementation tree = new
                      MerkleTreeImplementation(bigdata_items);

            foreach (string s in tree.BigDataOriginalItems)
            {
                Console.WriteLine(s);
            }
            Console.WriteLine("Hash integrity checking is:
                                        {0}", tree.GetRoot());
            Console.ReadKey();
        }
    }
}

Listing 16-2Simple Example of a Merkle Tree as Support for the Practibility of Verifiable Computation

using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;

namespace VerifiableComputation
{
    class MerkleTreeImplementation
    {
        private List<string> bigDataItems;
        private List<string> bigDataOriginalItems;

        public List<string> BigDataOriginalItems
        {
            get => bigDataOriginalItems;
            private set
            {
                bigDataOriginalItems = value;
                bigDataItems = value;
            }
        }

        public MerkleTreeImplementation(List<string> BigData_OriginalItems)
        {
            BigDataOriginalItems = BigData_OriginalItems;
            CreateTree();
        }

        public string GetRoot()
        {
            return bigDataItems[0];
        }

        private void CreateTree()
        {
            var data_items = bigDataItems;
            var temporary_data_items = new List<string>();

            //** using 2 element go and parse
           //** the list for items
            for (int i = 0; i < data_items.Count; i += 2)
            {
                //** Take the left element
                string left_element = data_items[i];

                //** the element from right is empty
                string right_element = String.Empty;

                //** once we have the proper item we will need
                //** to replace the empty string from above
                //** with the proper one
                if (i + 1 != data_items.Count)
                    right_element = data_items[i + 1];

                //** compute the hash for the left value
                string leftHash = HashTheBigData(left_element);

                //** if we we have the item from
                //** right as being empty we will hash it
                string rightHash = String.Empty;
                if (right_element != String.Empty)
                    rightHash = HashTheBigData(right_element);

                //** if we have the hash for right empty, we
                //** will add the sum of the left with right
                //** into temporary_items
                if (right_element != String.Empty)
                    temporary_data_items.Add
                                      (leftHash + rightHash);
                //** contrary, we will add the left hash only
                else
                    temporary_data_items.Add(leftHash);
            }

            //** if the size of the list is different from 1
            if (data_items.Count != 1)
            {
                //** once we are here we will replace replace
                //** bigDataItems with temporary_data_items
                bigDataItems = temporary_data_items;

               //** call again the function
                CreateTree();
            }
            else
                //** once we get 1 item then we can say that
                //** we have the root for the tree.
                //** we will save it at bigDataItems
                bigDataItems = temporary_data_items;
        }
        private string HashTheBigData(string bigData)
        {
            using (var sha256 = SHA256.Create())
            {
                //** use some big data volume
                byte[] hasshed_bytes_of_bigdata =
                  sha256.ComputeHash(Encoding.UTF8.
                                     GetBytes(bigData));

                //** take the hash value
                //** and work with it accordingly
                string current_hash_bigdata_value =
                       BitConverter.ToString(hasshed_bytes_of_b
                       igdata).Replace("-", "").ToLower();
                return current_hash_bigdata_value;
            }
        }
    }
}

Listing 16-1Implementation of a Merkle Tree as a Solution for a Simple Case of Verifiable Computation

安全多方计算

多方计算(MPC)代表了密码学的一个子领域,其主要目标是为多方提供方法,以加入对其输入的函数的计算过程,并秘密存储这些输入。在 [10 ]中,作者将 MPC 与可搜索加密相结合,以便为在真实的复杂环境中应用 MPC(见图 16-4 )提供一个实际的开端,如大数据和云计算。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 16-4

安全多方计算

在 [13 ]中,Claudio Orlandi 讨论了一个关于 MPC 适用性的有趣问题和担忧。在将 MPC 作为一种独立的机制在真实环境中使用之前,需要填补多项技术空白。事实上,研究社区已经提供了大量与 MPC 相关的文章,但是 80%以上都是纯理论,没有任何正确应用它的方向或意义。作者在 [6 - 9 ]和 [11 ]中对此方向做了其他贡献。

基于图 16-4 中描述的 MPC 场景,我们将考虑以下 MPC 场景,其组件来自图 16-5 。在 [10 中提出了 MPC 场景,它代表了 MPC 与可搜索加密方案和隐写对象的组合,隐写对象用作唯一识别存储在云和大数据环境中的文件和数据的标识符。为了实现 MPC 协议中数据的安全性,我们将重点介绍加密(图 16-4 中的步骤 3 )和解密(图 16-5 中的步骤 4.3 )。下面提出的算法是针对大数据应用而设计的,并且已经在真实环境中进行了测试,用于天气预报和分析,如 [10 中所述。加密和解密(参见清单 16-3 和 16-4 )是通过 RSA 算法(参见图 16-7 )实现的,该算法经过适当调整和设计,适用于大量数据。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 16-5

大数据中的 MPC

它与普通 RSA 实现的不同之处在于私钥被表示为一个 XML 文件(见图 16-6 )。您可以看到用于 RSA 初始化的所有必要参数。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 16-6

RSA XML 私钥

using System;
using System.Security.Cryptography;
using System.Text;

namespace RSACryptography
{
   public static class CryptographyHelper
    {
       private static bool asymmetricEncryptionPadding = false;

       //** keys of 2048 bytes length
       private readonly static string public_key = "MjA0OCE8UlNBS2V5VmFsdWU+PE1vZHVsdXM+djFTTVVyYk5SZW50VDEya0FhWXNRMEh3Y2hjWG9nbnFUWGpYd1NXaGR5Qi9aaTQ5VnF4L0lFdWxSaGFhVjdHOUtENWRmY0I4eEZaZGgyNGJ0MHpZbGFNTlFyRVBNNnQzUEdvZXZmMXVCby9wVnhlcWFocEFkWkIwelNJcjhwTk5UOW52czV5WEN1Q00xRFo0UUR3Q3A3b2U2aXc2ZHZ4VEZNWFZJdW9rSkcrdmlFMWhORDhnbGg0dFVsMWVBdThKT3YyR0tyWmhvTmUxK2tnRzNNUmRueEFGTDQyRDl4eWF5NERvcmpGL2ZjYWNNc3dFYkM3MUo2bFNobnR2YnQ1RnY0elY1bkg0aDhqYzhnV1dQVDUvWG16TElLMmlJRDJ6L3NyeGgvbzdMRkRhWVhXMnVwbUt5VUJQR2k0OGJLUVZKT3JjZU9rd3owWE1nTDFJUk4yWnhRPT08L01vZHVsdXM+PEV4cG9uZW50PkFRQUI8L0V4cG9uZW50PjwvUlNBS2V5VmFsdWU+";
       private readonly static string private_key = "MjA0OCE8UlNBS2V5VmFsdWU+PE1vZHVsdXM+djFTTVVyYk5SZW50VDEya0FhWXNRMEh3Y2hjWG9nbnFUWGpYd1NXaGR5Qi9aaTQ5VnF4L0ldWxSaGFhVjdHOUtENWRmY0I4eEZaZGgyNGJ0MHpZbGFNTlFyRVBNNnQzUEdvZXZmMXVCby9wVnhlcWFocEFkWkIwelNJcjhwTk5UOW52czV5WEN1Q00xRFo0UUR3Q3A3b2U2aXc2ZHZ4VEZNWFZJdW9rSkcrdmlFMWhORDhnbGg0dFVsMWVBdThKT3YyR0tyWmhvTmUxK2tnRzNNUmRueEFGTDQyRDl4eWF5NERvcmpGL2ZjYWNNc3dFYkM3MUo2bFNobnR2YnQ1RnY0elY1bkg0aDhqYzhnV1dQVDUvWG16TElLMmlJRDJ6L3NyeGgvbzdMRkRhWVhXMnVwbUt5VUJQR2k0OGJLUVZKT3JjZU9rd3owWE1nTDFJUk4yWnhRPT08L01vZHVsdXM+PEV4cG9uZW50PkFRQUI8L0V4cG9uZW50PjxQPi8yY1VJS2RlMFB1b2RVaDJQQ3krbFU0aWFvVWtOZ0dOOVhHNmhvcll3c1ovbzdwdTJYZjZmS2E5M09OZ1R0NUpqaW5QL3grZG9ibmFiU1hNNFNwRGJlb3JVRGZBKzhYeDIxTHBCT0FtYUtUVWlkejNjMHlQRXBQZ3lOMlpVb3poUWhjejZlUk01cUdQSlgxU29WMjczM3ZUREFtTEVWS0N4eFRZOHVNSWI3OD08L1A+PFE+djhjYlBmcHh5aXZUelhsV2Q5L3hNK3pRUlJRSk4rTDFIYURiNHYxKzU3dExEb3VlcG03ajI0MkJFZ2U4dTNENmJEanZneWhBWFIxV3IwR09KSjBBb1ZPV2FLLzdvZ3NHZjBnM1dzNzVicWtWSmdNTHZETnFxSVVVd0ZqZml3TllONkJnN0dIdGl2S0VGdmJldTEzcGFxVERyTnFuV0ZQaWFQK1lkQ09xVjNzPTwvUT48RFA+eWVSVDF0UTNjWC9kMUlocFhud0lVOEltRm9vVTY5UWl3YWtiUjR1dWVabXNBR001aVJMOG9WaTFzVXpVTHNRczVRSk1kMklvbTFWdFF1YWtwRUZpZUJxcURvbGtOaUp0WTNDUTN0Zkp4T0szV0J1aVNEUjJ6THEwOEZPc0JjTnp0V2plRXIvendrUm9BYnlsZXdXN281Z2dadDJNWHk4WVRnTSsxQkYvODhVPTwvRFA+PERRPlRGOUxYd1JFbW9HWHFJVkF4UjVlblJJYTR0ZVcwRFhHN1pTbzNKMmRFMFhJSHpQRTYzelBxeGlRSlJFRnZSUEI5cVU1NU41N3UxazZzektGRzltV2JhaXZCbVBHN3dJN0JTZEtQQlNleXMzMUNSMC9hQ1NGdmpTNVRkeFdzYktVU0JyTFhuZWxOS2RkcVJPSkljN0ZiTjNPdXlDY2NoVjkzZGlqNnVSbEtzOD08L0RRPjxJbnZlcnNlUT5rSmYwVHZoNDZjTEQ4OElIVVZ0V3hYaDVsYlNUTWw2ZnB5cFhhUU9laUtpTy9XcnZic21waXdBVEhDQ0pERDhYdDFwbTc5K0hrc21sUjlrYktXR2U4WmNqZHJHdUZlZ3NDUGRpT3VGMVN0a283NWtnblJVY0ZTb1hxSzF1YVgvTWsxTEtDbVpZY3djQ0t2VC9OQUZrWVpVdVNqT3pPckVrRk9VNDdML3VDVE09PC9JbnZlcnNlUT48RD5HbTMyZUZLU0pvODYzZFRFbkFtMVlaRVJRdUZYdldWN1BUcHRLMXdrWXMxVmErc0ZSQnpON3Nza1NIdEUxTXBUbytTQmk2WjBWYmJNY3JIT0dGTUFOQ055Nkh5RzZnOU1pRWJzZWpndzQ2MHJnWUZlWkF1K1RiOG5zMUorR2FNcGNkZGNHa2FPUXMxa0JzaURjZlFZTmMwckNoUVQrMjI5bUVmL3VqUDN6Q1IzcUNzdkZjVTRuMkMwZzBYSWhLQ1dHYXRsbW5MOW9FMWN0MzY4aWZYK0JCUVljUExqSE05TTZaSU9pMWtmR3M2bXhaT0V3cm1BWFB0T0ZweW1tNlZjMUM4WGtVUENCVERtWUZTSFpiaHNaT09IZHpaVVlUa2lmN1VzRk40MjdTSDVrMTNpQTVGRGJTb053bW9kQ0ZrWitENGJNQ2JUZWgwVTNvell6M3FnM1E9PTwvRD48L1JTQUtleVZhbHVlPg==";

       public static string Encrypt(string clearText)
       {
           int size_of_the_key = 0;
           string xmlWithPublicKey = "";

           GetKeyFromEncryptionString(public_key, out size_of_the_key, out xmlWithPublicKey);

           var encrypted = Encrypt(Encoding.UTF8.GetBytes(clearText), size_of_the_key, xmlWithPublicKey);

           return Convert.ToBase64String(encrypted);
       }

       private static byte[] Encrypt(byte[] data, int keySize, string publicKeyXml)
       {
           if (data == null || data.Length == 0)
                throw new ArgumentException("There is empty data", "data");

           int maximum_length = GetMaxDataLength(keySize);

           if (data.Length > maximum_length)
                throw new ArgumentException(String.Format("The maximum length of data is {0}", maximum_length), "data");

           if (!IsKeySizeValid(keySize))
                throw new ArgumentException("The size of the key is not valid", "keySize");

            if (String.IsNullOrEmpty(publicKeyXml))
                throw new ArgumentException("The key is null or empty", "publicKeyXml");

           using (var provider = new RSACryptoServiceProvider(keySize))
           {
               provider.FromXmlString(publicKeyXml);
               return provider.Encrypt(data, asymmetricEncryptionPadding);
           }
       }

       public static string Decrypt(string encryptedText)
       {
           int keySize = 0;
           string publicAndPrivateKeyXml = "";

           GetKeyFromEncryptionString(private_key, out keySize, out publicAndPrivateKeyXml);

           var decrypted = Decrypt(Convert.FromBase64String(encryptedText), keySize, publicAndPrivateKeyXml);

           return Encoding.UTF8.GetString(decrypted);
       }

       private static byte[] Decrypt(byte[] data, int keySize, string publicAndPrivateKeyXml)
       {
           if (data == null || data.Length == 0)
                throw new ArgumentException("The data is empty", "data");

            if (!IsKeySizeValid(keySize))
                throw new ArgumentException("The size of the key is not valid", "keySize");

            if (String.IsNullOrEmpty(publicAndPrivateKeyXml))
                throw new ArgumentException("The key is null or empty", "publicAndPrivateKeyXml");

           using (var provider = new RSACryptoServiceProvider(keySize))
           {
               provider.FromXmlString(publicAndPrivateKeyXml);
               return provider.Decrypt(data, asymmetricEncryptionPadding);
           }
       }

       private static int GetMaxDataLength(int keySize)
       {
           if (asymmetricEncryptionPadding)
           {
               return ((keySize - 384) / 8) + 7;
           }
           return ((keySize - 384) / 8) + 37;
       }

       private static bool IsKeySizeValid(int keySize)
       {
           return keySize >= 384 && keySize <= 16384 && keySize % 8 == 0;
       }

       private static void GetKeyFromEncryptionString(string rawkey, out int keySize, out string xmlKey)
       {
           keySize = 0;
           xmlKey = "";

           if (rawkey != null && rawkey.Length > 0)
           {
               byte[] keyBytes = Convert.FromBase64String(rawkey);
               var stringKey = Encoding.UTF8.GetString(keyBytes);

               if (stringKey.Contains("!"))
               {
                   var splittedValues = stringKey.Split(new char[] { '!' }, 2);

                   try
                   {
                       keySize = int.Parse(splittedValues[0]);
                       xmlKey = splittedValues[1];
                   }
                   catch (Exception e) { }
               }
           }
       }
    }
}

Listing 16-4

CryptographyHelper Class

using System;

namespace RSACryptography
{
    class Program
    {
        public static void Main(string[] args)
        {
            // encryption and decryption a password example
            var password = "P@sswrd123";

            Console.WriteLine("\n Original Password Text: " +
                                          password);

            var textToBeEncrypted =
                              CryptographyHelper.Encrypt(password);
            Console.WriteLine("\n Encrypted Password Text: " +
                                     textToBeEncrypted);

            var textToBeDecrypted =
                  CryptographyHelper.Decrypt(textToBeEncrypted);
            Console.WriteLine("\n Decrypted Password Text: " +
                                       textToBeDecrypted);

            //** encryption and decryption for database
           //** connection string
            var connectionString = "Data Source=USER-
                        Test\\SQLEXPRESS;Initial
                        Catalog=OrderProcessing;Integrated
                        Security=True";

            Console.WriteLine("\n Original Connection String
                                     Text: " + connectionString);

            textToBeEncrypted =
                CryptographyHelper.Encrypt(connectionString);
            Console.WriteLine("\n Encrypted Connection String
                                   Text: " + textToBeEncrypted);
            textToBeDecrypted =
                CryptographyHelper.Decrypt(textToBeEncrypted);
            Console.WriteLine("\n Decrypted Connection String
                                 Text: " + textToBeDecrypted);

            //** encryption and decryption of a very long
            //** query result from DB
            var longTextForEncryption = "Literally, Blockchain is a chain of blocks which could be simply assumed as an immutable data structure. Immutability is one of the most prominent features of a blockchain, which leads us to build trust in completely unreliable environments

.";

           Console.WriteLine("The encryption of the query is:
                  {0}",
                  CryptographyHelper.Encrypt
                         (longTextForEncryption));

            Console.ReadKey();
        }
    }
}

Listing 16-3RSA

for Big Volumes of Data (Encryption and Decryption Operations)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 16-7

大数据量和其他类型字符串的加密/解密输出。

对于类CryptographyHelperRSACryptographyKeyGenerator,请参见 GitHub 资源库中的完整项目。

结论

在本章中,我们讨论了拥有大数据环境的重要性,以及如何通过不同的加密机制实现安全性,例如可验证计算和多方计算。

在本章结束时,您现在已经了解了以下内容:

  • 云和大数据环境中的主要安全概念

  • 如何实现复杂的密码原语和协议,如可验证计算和多方计算

文献学

  1. 页(page 的缩写)Laud 和 A. Pankova,“诚实多数的多方协议中的可验证计算”,载于 S.S.M. Chow、J.K. Liu、L.C.K. Hui 和 S.M. Yiu (eds) 可证明的安全性。ProvSec 2014。计算机科学讲义,第 8782 卷。施普林格,查姆。2014.

  2. D.安全多方计算的遗忘排序算法的实际分析。在 K. Bernsmed 和 S. Fischer-Hübner (eds) 安全信息技术系统。NordSec 2014。计算机科学讲义,第 8788 卷。施普林格,查姆。2014.

  3. D.Bogdanov、L. Kamm、S. Laur 和 p . prulmann-Vengerfeldt,“安全多方数据分析:最终用户验证和实践实验”,2014 年。

  4. B.奥兹卡马克,a . özbi̇len,u .亚瓦诺格鲁,k . ci̇n,“大数据中的神经和量子密码术:综述”,2019 年 IEEE 大数据国际会议(大数据),美国加利福尼亚州洛杉矶,2019 年,第 2413-2417 页,doi:10.1109/big data 47090 . 20193409

  5. 南 Yakoubov,V. Gadepally,N. Schear,E. Shen 和 A. Yerukhimovich,“保护云中大数据分析的加密方法综述”,发表于 2014 年 IEEE 高性能极限计算会议(HPEC) ,马萨诸塞州沃尔瑟姆,2014 年,第 1-6 页,doi:10.1109/hpec . 2014 . 111191991

  6. 基于椭圆曲线的可搜索加密方案。在 Barolli L .、Amato F .、Moscato F .、Enokido T .、Takizawa m .编的《Web、人工智能和网络应用。怀娜 2020。智能系统和计算进展,第 1150 卷。施普林格,查姆。2020.

  7. 《云计算的混合可搜索加密方案》在 J.L. Lanet 和 C. Toma (eds) 创新的信息技术和通信安全解决方案。SECITC 2018。计算机科学讲义,第 11359 卷。施普林格,查姆。2019.

  8. 动词 (verb 的缩写)C. Pau 和 M. I. Mihailescu,“物联网及其在生物识别技术和电子学习应用中的作用”,载于 2015 年第十三届现代电气系统工程国际会议(EMES) ,(第 1-4 页)Oradea。doi:10.1109/emes . 2015.7158430 . 2015。

  9. 南 L. Nita 和 M. I. Mihailescu,“论用于云计算安全的人工神经网络——一项调查”,载于 2018 年第十届国际电子、计算机和人工智能会议(ECAI) (第 1-6 页)。雅西,罗马尼亚,doi:10.1109/ecai . 2018.86770858866

  10. Marius Iulian Mihailescu、Stefania Loredana Nita 和 Ciprian Racuciu,“适用于地球科学的基于可搜索加密和多方计算的认证协议”,载于海军学院科学通报,第二十三卷(第 221-230 页)。doi:10.21279/1454-864 x-20-I1-0302020.

  11. Marius Iulian Mihailescu、Stefania Loredana Nita 和 Ciprian Racuciu,“使用可搜索对称加密的多级访问及其对地球科学的适用性”,载于海军学院科学通报,第二十三卷(第 221-230 页),doi:10.21279/1454-864 x-20-I1-030。2020.

  12. Stefania Loredana Nita,Marius Iulian Mihailescu 和 Ciprian Racuciu,“使用 MapReduce 在云计算中进行安全文档搜索”,载于海军学院科学通报,第二十三卷(第 221-230 页),doi:10.21279/1454-864 x-20-I1-030。2020.

  13. RSA 大数据分析扩展。网上有: www.rsa.com/en-us/company/news/rsa-extends-big-data-analytics-to-help-organizations-identify

  14. Claudio Orlandi,多方计算在实践中有用吗?网上有: www.cs.au.dk/~orlandi/icassp-draft.pdf

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值