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

原文:Pro Cryptography and Cryptanalysis

协议:CC BY-NC-SA 4.0

十七、云计算密码术

云计算中的密码学代表了为客户端和复杂网络环境设计和实现安全应用的一个热点。云中的加密技术采用复杂的加密技术,目的是保护将在云环境中存储和稍后使用的数据。

组织已经迅速采用云技术作为 IaaS(基础设施即服务)、PaaS(平台即服务)和 SaaS(软件即服务)。原因包括带来的好处,如效率和灵活性,最终将降低成本。

以下密码学原语和机制也受到了研究团体和行业的关注:

  • 同态加密(参见第十三章

  • 可搜索加密(参见第十二章

  • 结构化加密(SE)

  • 功能加密

  • 私人信息检索

在本章中,我们将重点介绍结构化加密(STE)、函数加密、透明数据加密(TDE)和多方计算(MPC)。前两个原语,同态加密和可搜索加密,由于它们的重要性和发展,在章节中以相同的名称出现。

结构化加密

STE 方案的作用是为数据结构提供加密。STE 方案基于用于查询结构的某个令牌,该令牌能够给出查询的评估,并从结构或查询中了解最明确的泄漏。可搜索对称加密(SSE)(见第十二章)代表了 STE 的一个特例。快速提醒一下,SSE 将搜索结构加密为倒排索引或类似的搜索树。在实践中,SSE 为设计和实现搜索引擎提供了一个自然的解决方案(参见清单 12-2 )

  • 为数据集生成搜索结构并为其提供加密

  • 搜索特定关键字 w 并基于 w 生成令牌并继续查询加密结构

在图加密中可以找到类似的 STE 方案,它为使用图结构的加密数据库的设计阶段提供了一个有趣的解决方案。加密图形数据库以在社交搜索环境中保护其隐私是一个非常好的例子,特别是因为我们正在云计算环境中处理复杂的大数据基础设施,如大数据分析和统计。

作为本节框架的一个例子,我们将考虑一个使用基于图的加密技术的数据库加密算法(参见伪代码 17-1 和清单 17-1 )。在清单 17-2 中,你可以看到清单 17-1 中提出的框架的工作版本。输出如图 17-1 所示。该算法接收将被加密的 n 个字符作为的第一个输入,( ch 1ch 2chn)。从数据库中接收字符作为记录。第二输入由路径的起点( s p )和终点( e p )表示。第三个输入由被分析路径的长度表示( l p )。

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

图 17-1

使用图加密 SE

话虽如此,让我们看看清单 17-1 中的伪代码。

伪代码 17-1。算法的伪代码

)

)

INPUT:
      ch1, ch2, ..., chn − characters as single records
      sp − the starting point of the vertex path
      ep − the ending point of the vertex path
      lp − length path

)

      temporary ← chi
      generate a next path for linking sp and ep
      for j = lp downto 1 do begin
            temporary ← temporary XOR kj
            temporary ← temporary ⋘ 1
            temporary ← Π(temporary)
      end
      encryptedch(i) ← temp
      return the encrypted character, encryptedch(i)

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

namespace StructuredEncryptionUsingGraphEncryption
{
    class DBGraphEncrypt
    {
        //** this queries represents some constants which
       //** represents records from the database.
        public const int query1 = 255;
        //public const string query2 = "Address";
        //public const string query3 = "Phone number";

        public DBGraphEncrypt()
        {

        }

        static public byte[] Decryption(byte[] Data,
                    RSAParameters RSAKey, bool DoOAEPPadding)
        {
            try
            {
                byte[] decryptedData;
                using (RSACryptoServiceProvider RSA = new
                               RSACryptoServiceProvider())
                {
                    RSA.ImportParameters(RSAKey);
                    decryptedData = RSA.Decrypt(Data, DoOAEPPadding);
                }
                return decryptedData;
            }
            catch (CryptographicException e)
            {
                Console.WriteLine(e.ToString());
                return null;
            }
        }

        static public byte[] Encryption(byte[] Data,
                     RSAParameters RSAKey, bool DoOAEPPadding)
        {
            try
            {
                byte[] encryptedData;
                using (RSACryptoServiceProvider RSA = new
                                  RSACryptoServiceProvider())
                {
                    RSA.ImportParameters(RSAKey);
                    encryptedData = RSA.Encrypt(Data, DoOAEPPadding);
                }
                return encryptedData;
            }
            catch (CryptographicException e)
            {
                Console.WriteLine(e.Message);
                return null;
            }
        }

        private static void Print(int[,] distance, int verticesCount)
        {
            Console.WriteLine("Shortest distances between
                                        every pair of vertices:");

            for (int i = 0; i < verticesCount; ++i)
            {
                for (int j = 0; j < verticesCount; ++j)
                {
                    if (distance[i, j] == query1)
                        Console.Write("query1".PadLeft(7));
                    else
                        Console.Write(distance[i,
                                  j].ToString().PadLeft(7));
                }

                Console.WriteLine();
            }
        }

        public static void GraphSimulation(int[,] graph, int verticesCount)
        {
            int[,] distance = new int[verticesCount, verticesCount];

            for (int i = 0; i < verticesCount; ++i)
                for (int j = 0; j < verticesCount; ++j)
                    distance[i, j] = graph[i, j];

            for (int k = 0; k < verticesCount; ++k)
            {

                for (int i = 0; i < verticesCount; ++i)
                {
                    for (int j = 0; j < verticesCount; ++j)
                    {
                        if (distance[i, k] + distance[k, j] <
                                              distance[i, j])
                            distance[i, j] = distance[i, k] +
                                              distance[k, j];
                    }
                }
            }

            Print(distance, verticesCount);
        }

        static void Main(string[] args)
        {
            UnicodeEncoding ByteConverter = new UnicodeEncoding();
            RSACryptoServiceProvider RSA = new RSACryptoServiceProvider();

            int[,] databaseGraphRecords = {
                         { 0,   6,  query1, 11 },
                         { query1, 0,   4, query1 },
                         { query1, query1, 0,   2 },
                         { query1, query1, query1, 0 }
                           };

            byte[,] dataGraphForEncryption = new
                        byte[databaseGraphRecords.Length,
                        databaseGraphRecords.Length];
            byte[] dataForEncryption = new
                        byte[databaseGraphRecords.Length];
            string[] test = new
                        string[databaseGraphRecords.Length];

            int k = 0;
            for (int i = 0; i <
                    Math.Sqrt(databaseGraphRecords.Length); i++)
            {

                for (int j = 0; j <
                    Math.Sqrt(databaseGraphRecords.Length); j++)
                {
                    dataForEncryption[k] =
                          Convert.ToByte(databaseGraphRecords
                                                [i, j]);
                    k++;
                }
            }

            byte[] encryptions = Encryption(dataForEncryption,
                        RSA.ExportParameters(false), false);
            Console.WriteLine("The encryption of the records
                        graph from the database is:");
            for(int i = 0; i < encryptions.Length; i++)
            {
                Console.Write("0x" + encryptions[i].ToString()
                                                 + " ");
            }

            Console.WriteLine("\n");
            GraphSimulation(databaseGraphRecords, 4);

            Console.WriteLine("\n");
            byte[] decryptions = Decryption(encryptions,
                              RSA.ExportParameters(true), false);
            Console.WriteLine("The decryption of the records
                              graph from the database is:");
            for (int i = 0; i < decryptions.Length; i++)
            {
               Console.Write(decryptions[i].ToString() + " ");
            }
        }
    }
}

Listing 17-2Encryption of SE Using Graph

using System;

namespace GraphEncryptionDatabase
{
      class DBGraphEncrypt
      {
            //** starting point
            int sp;

            //** ending point;
            int ep;

            //** path length
            int lp;

            //** constructor
            public DBGraphEncrypt() {}

            public void GraphEncryption()
            {
                  //** let's declare an instance of the context
                  //** we will use Linq-to-Sql for this example

                  Apress_DBGraphEncExampleDataContext dbContext
                  = new Apress_DBGraphEncExampleDataContext();

                  //** create an instance of the class
                  //** generated for the table
                  EmployeeDetail emp_details = new
                                      EmployeeDetail();

                  //** select the record that
                  //** you want to encrypt
                  var query = (from emp in
                   dbContext.EmployeeDetails
                     select emp.Password).Single();

                  //** parse the record

                  string record = query.ToString();
                  for(int i=0; i<record.Length; i++)
                  {
                        char ch = record[i];
                        Encrypt(ch.ToString());
                  }
            }

            public string Encrypt(string ch)
            {
                  Encryption.useEncAlgorithm(new
                  Encryption(Encryption.ALGORITHM.GraphEnc));

                  string encryption_key;

                  Console.WriteLine("Enter the password :");
                       String password = encryption_key.readLine();

                  byte[] secret_key = GenerateKeys.keyGen(256,
                            password, "salt/salt", 100000);

                  Console.WriteLine("Return the records
                           (strings) that will be encrypted.");
                  String pathName = encryption_key.readLine();

                  ArrayList<string> listOfCharacters = new
                                          ArrayList<string>();
                  listOfCharacters.Add(ch);

                  //** parse the listOfCharacters
                  //** parameters of the graph vertex for the
                  //** size of the data set
                  //** change in such way that you will get a
                  //** better performance
                  int big_block = 700;
                  int small_block = 120;
                  int size_of_data = 12000;

                  while (true)
                  {
                        Console.WriteLine("Enter the keyword tosearch for:");
                        String keyword = Console.Read();
                        byte[][] token_encryption_key =
                          GraphEnc.token(secret_key , keyword);
                        Console.WriteLine(GraphEnc.resolve(CryptoPrimitives.
                generateGraphEnc(secret_key, 3 + new String()),
                generateGraphEnc.query(GraphEnc.GeneratePath(sp, ep, lp),
                   GraphEnc.generateListOfCharacters(),
                   GraphEnc.Encrypt())));
                  }
            }
      }
}

Listing 17-1The Implementation

OUTPUT:
      encryptedch(1), encryptedch(2),, encryptedch(n)

功能加密

函数加密是公钥加密的推广。在这种类型的加密中,拥有秘密密钥允许人们了解正在加密的密文的功能。FE 是复杂的,它有几个子类,如谓词加密、基于身份的加密、基于属性的加密(ABE)、密文策略 ABE、隐藏向量加密和内积谓词。

函数加密方案表示由四种算法组成的元组,例如 setup、keygen、encryption 和 decryption。正确性需要满足一个条件,即 kKxX :

  • 设置 (1 λ ) → ( 公共 按键 按键 )

  • ( ) →

  • 加密 ( 公开密钥消息 ) → 密文

  • 解密 ( 秘密密钥密文 ) → y

上面的步骤可以在下面的清单 17-3 中调换,其中我们介绍了一个通用函数加密方法应该如何实现的通用框架。清单 17-3 中的例子并不代表可以编译和执行的例子。由于其复杂性和应用,给出一个 FE 的实现可能是一个非常具有挑战性的任务。

//** generating master keys and FE key

//** length of input vectors
int input_vector_length = 2;

//** the upper limit for input vector coordinates
Random rand = new Random();
int bound = rand.Next();

//** length in bit of the prime modulus
int length_of_modulus = 2048;

trusted_entity = GenerateNewVector(input_vector_length,
                                     length_of_modulus, bound);
master_key = trusted_entity.GenerateMasterKey();
master_public_key = trusted_entity.GenerateMasterPublicKey();

int y = data. GenerateNewVector ([]*big.Int{big.NewInt(1),
                                     big.NewInt(2)});
functional_encryption_key =
           trusted_entity.KeyDerivation(master_secret_key, y);

//** create a simulation of encryptor
//** our encryption will hide the message (x) using
//** master public key by the trusted entity
Encryption = GenerateParameters(trusted_entity.Parameters);
message = GenerateNewVector([]*rand.Next{rand.Next(3) rand.Next(4)});,
cipher = encryption.Encrypt(message, master_public_key);

//** create simulation of the decryptor that decrypts the cipher
Decryption = GenerateParameters(trusted_entity.Parameters);

//** do the decryption in order to get the result
//** inner prod of x and y
//** we are expecting xy to be 11 (e.g. <[1,2],[3,4]>)
xy = Decrypt(cipher, functional_encryption_key, y) ;

Listing 17-3Simple Implementation and Startup for FE

在清单 17-4 和图 17-4 中,我们提供了一个用于函数加密的公钥加密模块的实现示例。该示例设计用于包含敏感数据(如大量数据、查询结果等)的文件的云架构。).在从 GitHub 库运行清单 17-4 的项目之前,确保您已经使用来自开发者命令提示符的makecert命令正确地创建了证书(参见图 17-2 )。为此,您需要运行以下命令:

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

图 17-2

使用 makecert 创建证书

makecert -r -pe -n "CN=CERT_APRESS_FUNCTIONALENCRYPTION_CERT" -b 01/01/2020 -e 01/12/2020 -sky exchange -ss my

下一步是通过检查控制台窗口来验证证书是否被正确导入(参见图 17-3 )。

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

图 17-3

导入证书

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

namespace FunctionalEncryption
{
    class Program
    {
        //** variables for different paths, such as encryption
        //** and decryption path for folder
     private static string encryption_folder = @"D:\Encrypt\";
     private static string decryption_folder = @"D:\Decrypt\";
     private static string genuine_file = "TestData.txt";
     private static string encrypted_file = "TestData.enc";

        static void Main(string[] args)
        {
            //** create a stream as input file
            //** for encrypting test data
            StreamWriter stream_writer =
                    File.CreateText(genuine_file);
            stream_writer.WriteLine("Data as test to be encrypted");
            stream_writer.Close();

            //** use the certificate for encrypting the key
            X509Certificate2 certificateUsedForEncryption =
                  ObtainTheCertificateFromTheStore("CN=CERT_APRE
                  SS_FUNCTIONALENCRYPTION_CERT");
            if (certificateUsedForEncryption == null)
            {
                Console.WriteLine("Certificate
                     'CN=CERT_APRESS_FUNCTIONALENCRYPTION_CERT'
                     was not found.");
                Console.ReadLine();
            }

            //**  Do the encryption of the file using the
            //** public key from the certificate
            FileEncryption(genuine_file,
             (RSA)certificateUsedForEncryption.PublicKey.Key);

            //** Do the decryption of the file based on the
            //** private key obtained from the certificate
            FileDecryption(encrypted_file,
             certificateUsedForEncryption.GetRSAPrivateKey());

            //** Show in the console the
            //** genuine data and the decrypted data
            Console.WriteLine("Genuine message:   {0}",
                             File.ReadAllText(genuine_file));
            Console.WriteLine("Round Trip: {0}",
                          File.ReadAllText(decryption_folder +
                   genuine_file));
            Console.WriteLine("Press any key to continue.");
            Console.ReadLine();
        }

        private static X509Certificate2
                  ObtainTheCertificateFromTheStore(string
                   certificate_name)
        {

            //** go to the certification store and make sure
            //** that you are under the current user
            X509Store certification_store = new
                    X509Store(StoreLocation.CurrentUser);
            try
            {
                certification_store.Open(OpenFlags.ReadOnly);

                //** entire collection of certificates should
                //** be added to X509Certificate2Collection object.
                X509Certificate2Collection
                            collection_of_certifications =
                            certification_store.Certificates;

                //** validate the certificate
                X509Certificate2Collection
                       current_certificates =
                       collection_of_certifications.Find(
                       X509FindType.FindByTimeValid,
                       DateTime.Now, false);
                       X509Certificate2Collection
                       signing_certificate =
                       current_certificates.Find(X509FindType.
                       FindBySubjectDistinguishedName, certificate_name, false);
                if (signing_certificate.Count == 0)
                    return null;

                //** get the first certificate
                //** from the collection
                return signing_certificate[0];
            }
            finally
            {
                certification_store.Close();
            }
        }

        //** based on the public key encrypt the file
        private static void FileEncryption(string input_file,
                                          RSA rsaPublicKey)
        {
            using (Aes aes_algorithm = Aes.Create())
            {
                // Create instance of Aes for
                // symetric encryption of the data.
                aes_algorithm.KeySize = 256;
                aes_algorithm.Mode = CipherMode.CBC;
                using (ICryptoTransform
                              transforming_operations =
                              aes_algorithm.CreateEncryptor())
                {
                    RSAPKCS1KeyExchangeFormatter
                              formatOfTheKey = new
                              RSAPKCS1KeyExchangeFormatter
                                          (rsaPublicKey);
                    byte[] encryption_of_the_key =
                      formatOfTheKey.CreateKeyExchange(
                            aes_algorithm.Key,
                               aes_algorithm.GetType());

                    // Create byte arrays to contain
                    // the length values of the key and IV.
                    byte[] key_length = new byte[4];
                    byte[] initializing_vector_length = new byte[4];

                    int length_of_the_key =
                           encryption_of_the_key.Length;
                    key_length =
                     BitConverter.GetBytes(length_of_the_key);
                    int length_of_initializing_vector =
                                       aes_algorithm.IV.Length;
                    initializing_vector_length =
                           BitConverter.GetBytes(
                               length_of_initializing_vector);

                    //** the following will written in the
                    //** encrypted file
                    //** - length of the key
                    //** - length of the initializing vector
                    //** - encrypted key
                    //** - the initializing vector
                    //** - the encryption of the cipher
                    //** content
                    int start_file_name =
                        input_file.LastIndexOf("\\") + 1;

                    //** change the file's extension to ".enc"
                    string output_file = encryption_folder +
                        input_file.Substring(start_file_name,
                        input_file.LastIndexOf(".") –
                        start_file_name) + ".enc";
         Directory.CreateDirectory(encryption_folder);

                    using (FileStream output_file_stream = new
                               FileStream(output_file,
                               FileMode.Create))
                    {

                        output_file_stream.Write(
                                    key_length, 0, 4);

                        output_file_stream.Write(
                           initializing_vector_length, 0, 4);

                        output_file_stream.Write(
                           encryption_of_the_key, 0,
                           length_of_the_key);

                        output_file_stream.Write(aes_algorithm.
                           IV, 0, length_of_initializing_vector);

                        //** proceed with writting the cipher
                        //** text based on the cryptostream
                        //** used for encryption
                        using (CryptoStream
                                ouput_stream_encrypted = new
                                CryptoStream(output_file_stream,
                                transforming_operations,
                                CryptoStreamMode.Write))
                        {
                        //** save memory by proceeding with encryption of
                        //** different chunks at a time
                            int count = 0;

                        //** size_bytes_of_block can
                        //** represent a randomly size
                            int size_bytes_of_block =
                                      aes_algorithm.BlockSize / 8;
                            byte[] data_block = new
                                      byte[size_bytes_of_block];
                            int bytesRead = 0;

                            using (FileStream
                                      input_file_stream = new
                                             FileStream(input_file,
                                             FileMode.Open))
                            {
                                do
                                {
                                    count =
                                           input_file_stream.Read(
                                         data_block, 0,
                                                size_bytes_of_block);

                                             ouput_stream_encrypted.
                                                   Write(data_block,
                                                   0, count);
                                    bytesRead += count;
                                }
                                while (count > 0);
                                input_file_stream.Close();
                            }

                                ouput_stream_encrypted.
                                      FlushFinalBlock();
                            ouput_stream_encrypted.Close();
                        }
                        output_file_stream.Close();
                    }
                }
            }
        }

        private static void FileDecryption(string inFile, RSA rsaPrivateKey)
        {
            //** create an object as AES for providing
            //** symmetric decryption for our data
            using (Aes aes_algorithm = Aes.Create())
            {
                aes_algorithm.KeySize = 256;
                aes_algorithm.Mode = CipherMode.CBC;

                //** declare byte arrays and obtain their
                //** length for the key encryption and
                //** initializing vector
                byte[] length_of_key = new byte[4];
             byte[] length_initializing_vector = new byte[4];

              //** generate the file name for decryption file
                string output_file = decryption_folder +
                          inFile.Substring(0,
                          inFile.LastIndexOf(".")) + ".txt";

                //** declare file stream objects for reading
                //** the encrypted file (input_file_stream)
                //** and save the decrypted file in
                //** output_file_stream
                using (FileStream input_file_stream = new
                          FileStream(encryption_folder + inFile,
                          FileMode.Open))
                {

                 input_file_stream.Seek(0, SeekOrigin.Begin);
                 input_file_stream.Seek(0, SeekOrigin.Begin);
                 input_file_stream.Read(length_of_key, 0, 3);
                 input_file_stream.Seek(4, SeekOrigin.Begin);

                 input_file_stream.Read(
                         length_initializing_vector, 0, 3);

                    //** do the conversion of
                    //** the lengths to integers
                    int key_length =
                          BitConverter.ToInt32(length_of_key, 0);
                    int initialzing_vector_length =
                          BitConverter.ToInt32(
                                length_initializing_vector, 0);

                    //** check and get the start position for
                    //** the cipher text (start_pos_cipher) and
                    //** the length of it (length_cipher)
                    int start_pos_cipher = key_length +
                                initialzing_vector_length + 8;
                    int length_cipher =
                                (int)input_file_stream.Length –
                                              start_pos_cipher;

                    //** declare byte arrays and use them for
                    //** encrypted AES key, initializing
                    //** vector, and the encrypted text
                    byte[] encryption_of_the_key = new byte[key_length];
                    byte[] initializing_vector = new
                                byte[initialzing_vector_length];

                    //** do the extraction of the keys and
                    //** initializing vector by starting from
                    //** index position 8
                    input_file_stream.Seek(8,
                             SeekOrigin.Begin);

                    input_file_stream.Read(
                             encryption_of_the_key, 0, key_length);
                    input_file_stream.Seek(8 + key_length,
                             SeekOrigin.Begin);

                    input_file_stream.Read(initializing_vector,
                                0, initialzing_vector_length);

                    Directory.CreateDirectory(decryption_folder);

                    //** we will use RSA to decrypt AES key
                    byte[] decryption_key =
                         rsaPrivateKey.Decrypt(
                               encryption_of_the_key,
                               RSAEncryptionPadding.Pkcs1);

                    //** do the decryption of the keys
                    using (ICryptoTransform transform =
                         aes_algorithm.CreateDecryptor(
                         decryption_key, initializing_vector))
                    {
                        //** do the decryption of the cipher
                        //** text from the file stream used
                        //** for encryption (input_file_stream) //** to the file stream used for
                        //** decryption (output_file_stream)
                      using (FileStream output_file_stream  new
                                FileStream(output_file,
                                FileMode.Create))
                        {
                            int count = 0;

                                 int blockSizeBytes =
                                      aes_algorithm.BlockSize / 8;
                            byte[] data = new
                                      byte[blockSizeBytes];

                            //** save memory
                            input_file_stream.Seek(
                                       start_pos_cipher,
                                       SeekOrigin.Begin);
                            using (CryptoStream
                                       outStreamDecrypted = new
                                   CryptoStream(output_file_stream,
                                       transform, CryptoStreamMode.Write))
                            {
                                do
                                {
                                    count =
                                             input_file_stream.Read(
                                             data, 0,
                                             blockSizeBytes);

                                             outStreamDecrypted.Write
                                             (data, 0, count);
                                }
                                while (count > 0);

                                             outStreamDecrypted.FlushFinal
                                             Block();
                                outStreamDecrypted.Close();
                            }
                            output_file_stream.Close();
                        }
                        input_file_stream.Close();
                    }
                }
            }
        }
    }
}

Listing 17-4Implementation of X509 Public Key Encryption as Part of Functional Encryption

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

图 17-4

使用 X509 证书进行加密和解密的功能加密

私人信息检索

私有信息检索是一种协议,允许客户端检索数据库的元素,而数据库的所有者不能确定选择了哪些元素。

下面,您将看到一个实施 PIR 的示例。以下示例无法编译,因为它们代表了可在现实环境中应用的框架的一般结构。它可以被视为一个应用,帮助最终用户(客户端)从云环境(服务器)与数据库进行交互。清单 17-5 中的实现代表了用参与者的密钥加密参与者的一般方法(见图 17-5 ),这些密钥需要在数据库查询过程中进行交换。使用简单的同态方法生成密钥(参见第十三章)。所提供的例子是为处理数据库记录而设计的,如伪代码 17-2 和 17-3 所示。

伪代码 17-2。实施 PIR–客户端

using System;

namespace PrivateInformationRetrieval
{
      public class PIRExample
      {
            protected PIRExample pir;
            protected PIRExampleServer srv;
            protected Object parameters;

            public PIRExample(PIRExample pir,
                              PIRExampleServer srv)
            {
                  this.pir = pir;
                  this.srv = srv;
                  this.parameters = pir.generateParameters();
            }

            //** i represents the index
            public Object get(int i)
            {
                  try
                  {
                        int size = srv.size();
                        if (i < 0 || i >= size)
                              return null;

                        int maximum_width = srv.width();
                        PIRExample.Query query =
                        pir.generateQuery(parameters,
                                            i, size, maximum_width);

                        Object the_response =
                                       srv.generateResponse(query);

                        Object result_output =
                                    pir.processResponse(parameters,
                                                        the_response,
                                                         i, size,
                                                         maximum_width);

                         return result_output;
                  }

                  catch (Exception e)
                  {
                        return null;
                  }
            }

            public int size() {
                  try
                   {
                       Console.WriteLine(srv.size().ToString());
                       return srv.size();
                  }
                  catch (Exception e)
                  {
                        return 0;
                  }
            }

            public int width() {
                  try
                   {
                       Console.WriteLine(srv.size().ToString());
                       return srv.size();
                  }
                  catch (Exception e)
                  {
                        return 0;
                  }
            }

            public PIRExample pir() {return pir;}

            public PIRExampleServer srv() {return srv;}
      }
}

伪代码 17-3。实施 PIR

using System;

namespace PrivateInformationRetrieval
{
      public interface PrivateInformationRetrieval
      {
            public class TheQuery
            {
                  public int maximum_width;
                  public Object query;

                  public TheQuery(int maximum_width, Object query)
                  {
                        this.maximum_width = maximum_width;
                        this.query = query;
                  }
            }

            public Object    generateParams();
            public TheQuery  generateQuery(Object parameters,
                                          int the_index,
                                          int the_size,
                                          int maximum_width);
            public Object generateResponse(List database,
                                                 int width,
                                                 TheQuery query);
      public BigInteger processResponse(Object parameters,
                                              Object the_response,
                                               int the_index,
                                               int the_size,
                                               int maximum_width);
      }
}

在清单 17-5 中,我们介绍了一种实用的方法,展示了如何使用同态方法为私人信息检索生成密钥。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Numerics;
using System.Text;
using System.Threading.Tasks;

namespace PrivateInformationRetrieval
{
    class Program
    {
        static BigInteger PrivateKey;
        static BigInteger[] PublicKey;
        static readonly int val1 = 5;
        static readonly int val2 = 3;
        static string At = string.Empty;
        static string Bt = string.Empty;

        static void Main(string[] args)
        {

            Random rnd = new Random();
            byte[] rand = new byte[16];

            do
            {
                rnd.NextBytes(rand);
                PrivateKey = new BigInteger(rand);
                PrivateKey = BigInteger.Abs(PrivateKey);
            }
            while (BigInteger.GreatestCommonDivisor
                                (PrivateKey, 1000000) != 1);

            PublicKey = new BigInteger[100];

            for (int i = 0; i < 100; i++)
            {
                rnd.NextBytes(rand);
                PublicKey[i] = new BigInteger(rand);
                PublicKey[i] = (BigInteger.Abs(PublicKey[i]) *
                                PrivateKey) + (1000000 *
                                rnd.Next(10, 100));
            }
            Encryption();

            Console.WriteLine("\n The multiplication is:");
            multiplication();
            Console.WriteLine("\n The addition is:");
            addition();

            Console.ReadKey();
        }

        static void Encryption()
        {
           BigInteger A;
           BigInteger.TryParse(Convert.ToString(val1), out A);
           BigInteger B;
           BigInteger.TryParse(Convert.ToString(val2), out B);

            if (!(A < 1000000 && A >= 0) || !(B < 1000000 && B
                                                                >= 0))
            {
                Console.WriteLine("This values are not
                         avaialble. The numbers and the results
                         obtained has to be situated between 0
                         and 1000000\. These values cannot be
                         accepted");

            }
            else if (!(A * B < 1000000) && !(A + B < 1000000))
            {
                Console.WriteLine("These values are not valid
                         because neither multiplication nor sum
                         can be realized due to noise
                         accumulation. The numbers and results of
                         operations must range from zero to
                         999999  \nSuch values are unacceptable.
                         It is impossible to decrypt
                         multiplication and sum due to the NOISE
                         in ciphertext. Numbers and results of
                         operations have to be from zero to
                         999999");
            }
            BigInteger t = new BigInteger(0);

            //** Encryption for A
            Random rand = new Random();
            for (int i = 0; i < 100; i++)
            {
                if (rand.Next(2) == 1)
                    t = t + PublicKey[i];
            }
            At = (A + t).ToString();

            Console.WriteLine(At);

            t = 0;
            rand = new Random();

            //Encryuption for B
            for (int i = 0; i < 100; i++)
            {
                if (rand.Next(2) == 1)
                    t = t + PublicKey[i];
            }
            Bt = (B + t).ToString();
            Console.WriteLine(Bt);
        }

        public static void multiplication()
        {
            BigInteger A;
            BigInteger.TryParse(At, out A);
            BigInteger B;
            BigInteger.TryParse(Bt, out B);

            Console.WriteLine("Multiplication of A={0} and
                   B={1} is {2}", A, B, (A * B).ToString());
        }

        public static void addition()
        {
            BigInteger A;
            BigInteger.TryParse(At, out A);
            BigInteger B;
            BigInteger.TryParse(Bt, out B);

            Console.WriteLine("Addition of A={0} and B={1} is
                                 {2}", A, B, (A + B).ToString());
        }
    }
}

Listing 17-5Practical Approach for Generating Cryptographic Keys Using a Homomorphic Method for Private Information Retrieval

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

图 17-5

PIR 的同态加法

结论

本章讲述了云环境中最重要的加密原语。现在,您应该理解了高级概念和加密原语,以及它们的一般实现。

本章介绍的概念将为您提供坚实的实践基础,帮助您更深入地了解其他加密原语,如多方计算、透明数据加密或属性保持加密。

云计算密码学代表着强大的挑战,大量的文献提供了多种理论框架,但没有实践方向。这为专业人员和研究人员提供了强大的研究方向和目标,即开发新的想法来提高云环境中的安全性,但云解决方案提供商提供的标准安全策略除外。

文献学

  1. Rishav Chatterjee,Sharmistha Roy 和 Ug Scholar,“云计算中的密码学:确保云中安全性的基本方法”2017.

  2. 名词(noun 的缩写)Jaber 和 Mohamad Fadli Bin Zolkipli,“密码学在云计算中的应用”,2013 年 IEEE 控制系统、计算和工程国际会议*(第 179-184 页),Mindeb,2013 年,doi:10.1109/ic 欧安会。20137.888886866103*

  3. 云计算中的安全问题和密码学的使用。" 2014.

  4. Melissa Chase 和 Seny Kamara,“结构化加密和受控披露”,载于密码学进展-ASIACRYPT (第 577-594 页)。10.1007/978-3-642-17373-8_33.2010.

  5. 米(meter 的缩写))Brenner、J. Wiebelitz、G. V. Voigt 和 M. Smith,“应用同态加密的云中的秘密程序执行”,载于第 5 届 IEEE 数字生态系统和技术国际会议的会议录(IEEE DEST 2011)。

十八、密码分析入门

本书的第三部分将重点介绍密码分析及其方法。如第一部分所述,密码分析被定义为研究在密码算法和安全系统中寻找漏洞的方法和途径的学科。最重要的目标是获取加密消息或密钥的真实性质。

密码分析是由专业人员(职业黑客、信息安全官员等)进行的过程。).法律框架之外的密码分析活动被称为黑客攻击,涵盖个人和非个人利益。然而,最近,术语黑客已经流行为仅仅写代码,因此有人参与黑客马拉松活动。黑客马拉松一般与安全相关的编程无关,等等。

这本书的第三部分的任务是涵盖最重要的方法和技术,用于进行一般和深入的密码分析。我们将指出必要的密码分析工具,如软件、方法、密码分析类型、密码分析算法和渗透测试平台。

执行密码分析可能是一项棘手而困难的任务。在实现密码分析过程之前,必须考虑多个方面。如果密码分析过程由一个法律实体来执行,事情就变得简单了。如果密码分析过程是由一个非法人实体实现的,那么这将是一个更复杂的过程,并且会涉及黑客手段。黑客方法将在我们后面的讨论中指出。在这两种情况下,手都会变脏。在执行密码分析过程时,要考虑到这样一个事实:由于系统的复杂性、加密密钥的大容量、硬件平台、访问权限等原因,这一过程非常耗时,并且会遇到许多障碍。

与密码学相比,密码分析更有吸引力和挑战性。密码分析人员应该具备的知识非常复杂。密码分析人员应该关注的领域可以分为三大类,信息学(计算机科学)、计算机工程、数学。让我们为每个类别指定如下重要规则:

  • 信息学(计算机科学):计算机网络、编程语言、数据库、操作系统、理论密码学

  • 计算机工程和硬件 : FPGA(现场可编程网关阵列)、编程语言(如 VHDL)、开发平台(Xilinx 等。)

  • 数学:数论、代数、组合学、信息论、概率论、统计分析、椭圆曲线数学、离散数学、微积分、格子、实分析、复分析、傅立叶分析

第三方结构

本书第三部分的结构如下:

  • 第十九章。本章将涵盖密码分析技术的分类。我们将对算法复杂性理论、统计信息分析、无扰动编码、经典密码的密码分析、分组密码的密码分析等做一个快速的概述。

** 第二十章。本章将涵盖线性和差分密码分析,这在进行密码分析时至关重要。

**   *第二十一章*[](21.html)**。本章将涵盖整数密码分析攻击,这种攻击用于建立在置换网络上的分组密码。**

**   *第二十二章*[](22.html)**。本章将讨论攻击以及它们在实践中的应用。我们将介绍一种带有指南的方法,并展示如何使用 C# 设计和实现真正的攻击。**

**   *第二十三章*[](23.html)**。本章将讨论最重要的文本特征化技术。大多数基于文本特征的方法计算字符或字符串出现的数量。我们将讨论卡方统计等算法;monogram、bigram 和 trigram 频率计数;和四元图统计作为适合度度量。**

**   *第二十四章*[](24.html)**。本章将介绍实现密码分析方法的案例研究。******* 

**## 密码分析术语

本节讨论密码分析和道德黑客中最常用的术语。表 18-1 列出了密码分析领域经常使用的关键词和术语。当我们处理密码分析攻击和道德黑客攻击时,这些术语非常重要。以下术语将为您提供该过程的清晰图像,以及谁与什么进行交互。

表 18-1

密码分析术语

|

关键词/术语

|

定义

|
| — | — |
| 布莱克有黑客 | 黑帽黑客就是心怀不轨,闯入计算机系统或网络的人。他们的目的是利用任何安全漏洞获取经济利益,窃取和破坏机密和私人数据,关闭系统和网站,破坏网络通信,等等。 |
| 格雷有黑客 | 灰帽黑客是一个被称为黑客的人,他利用计算机系统或软件产品的安全弱点,目的是让这些弱点引起所有者的注意。与黑帽黑客相比,灰帽黑客采取行动没有任何恶意。“灰帽子”的总体目标是提供解决方案,改善计算机系统和网络安全。 |
| 白帽黑客/道德黑客 | 白帽黑客是为政府或组织工作或受雇于政府或组织的授权人员或认证黑客,其目标是执行渗透测试并找出系统中的漏洞。 |
| 格林有黑客 | 一个灰色帽子黑客是一个业余爱好者,但不同于一个 ?? 脚本小子。他们的目的是成为一名成熟的黑客。 |
| 脚本小子 | 脚本小子是最危险的黑客形式。一个
脚本小子
是一个没有太多技能的人,他使用其他黑客提供的脚本或下载工具。他们的目标是攻击网络基础设施和计算机系统。他们希望给他们的社区或朋友留下深刻印象。 |
| Blue 有黑客 | 蓝帽黑客类似于脚本小子。他们是黑客领域的初学者。如果有人敢嘲笑脚本小子,蓝帽黑客就会报复。蓝帽黑客会报复那些向他们挑战的人。 |
| Red hat 黑客 | 也被称为鹰眼黑客,他们的目标是阻止黑帽黑客。操作方式不同。在处理来自黑帽黑客的恶意软件行为时,他们是无情的。红帽黑客实施的攻击非常具有攻击性。 |
| 黑客活动分子 | 也被称为在线活动家,黑客行动主义者是一群匿名黑客中的一员,他们可以未经授权访问存储在政府计算机和网络中的文件,进而影响社会或政治党派和团体。 |
| 恶意内幕人士/告密者 | 这些人可能是公司或政府机构的员工,他们知道机构内正在发生的非法行为。这可能导致个人通过勒索该机构而获利。 |
| 国家或民族支持的黑客 | 由政府安排和指派的人员,其目标是提供信息安全服务并获取不同国家的机密信息。 |

一点密码分析的历史

写一部全面的密码分析史是具有挑战性的,令人着迷的,也是困难的。在这一节中,我们将介绍影响密码分析作为一个独立领域的一些主要时刻,以及它是如何在不同的历史时期演变的。

密码分析的历史从阿拉伯哲学之父 Al-Kindi (801-873)开始。他开发了一种独特的方法,利用字母出现频率的变化。这种方法帮助他分析和开发了破解密码的不同方法(如频率分析)。Al-Kindi 的工作是基于 Al-Khalil(717-786)的工作。Al-Khalil 的作品名为*密码信息之书,*描述了大多数可能的阿拉伯语单词的排列和组合,有元音和没有元音。

学习密码分析和密码学历史的最好方法是将时间分成几个短的时间段,并考虑这些时间段内发生的事件。密码分析历史的检查必须在考虑到密码学的情况下进行。以下事件提供了密码分析历史的快速概述,并集中在每个时期最重要的成就。

  • 公元前 600 年 : 斯巴达人创造了《scytale》的基础。镰刀的目的是在战斗中传递秘密信息。这个“装置”由两个部分组成,一条皮带和一根木杆。要解密信息,木杆必须有特定的大小。该大小必须与用于消息加密阶段的大小相同。如果接收者或恶意者没有相同的木杆大小,消息就无法解密。

  • 公元前 60 年 : 朱利叶斯·凯撒设计了第一个替代密码,它使用三点字符的移位技术来加密信息,这样 A 就是 D,B 就是 E,以此类推。这个密码的实现可以在章节 1 中看到。

  • 1474:Cicco Simonetta制作了一本拉丁和意大利文本的解密手册。

  • 1523 : 布莱斯·德·维根内尔创造了一种加密密码的基础,被称为维根内尔密码

  • 1553 : 吉奥万·巴蒂斯塔·贝拉索根据一个加密密钥设计出第一个密码。加密密钥基于发送方和接收方共同同意的一个字。

  • 1854 年 : 查尔斯·惠斯通创造了公平密码。该密码加密一组特定的字母,而不是一个字母一个字母地加密。这给密码带来了更高的复杂性,因此更难破解。

  • 1917 : 爱德华·赫本制造出第一台基于转子的机电机器。转子用于加密操作。加密密钥存储在旋转盘中。它是基于用于替换的表而设计的。该表随着键入的每个字符而被修改。

  • 1918 年 : 亚瑟·谢尔比乌斯发明了恩尼格玛机。第一个模型和原型是为商业目的而设计的。英格玛机器使用几个转子而不是一个,就像爱德华·赫本的机电机器一样。他的发明立即被德国军事情报部门采用,用于对他们的传输进行编码。

  • 1932 年 : 马里安·雷耶夫斯基发现了恩尼格玛机是如何工作的。1939 年,法国和英国情报部门使用波兰提供的信息,帮助艾伦·图灵等密码学家破解密钥,密钥每天都在变化。这对于二战中盟军的胜利至关重要。

  • 1945 年 : Claude E. Shannon 凭借其名为*的著作《密码学的数学理论》革新了密码学和密码分析。*这是一个里程碑,标志着经典加密技术的终结和现代加密技术的开始。

  • 1970 年底:IBM 的科学家设计出第一个分组密码。目标是保护客户的数据。

  • 1973 年:分组密码被美国采用,并被设定为国家标准,称为 DES(数据加密标准)。

  • 1975 年:公钥密码学问世。

  • 1976 年:介绍了密钥交换协议 Diffie-Hellamn。

  • 1982 :量子计算机的理论模型由理查德·费曼提出。此时此刻,我们即将拥有广泛可用的基于云的量子计算机。这些方面和进步将对今天和未来的计算的许多方面产生深远的影响。

  • 1997 : DES 破解成功。

  • 1994 : 彼得·肖介绍了一种可以在量子计算机中用于整数因式分解的算法。

  • 1998 :量子计算介绍。

  • 2000 年:正式用 AES(高级加密标准)取代 DES。AES 被宣布为公开竞赛的获胜者。

这个列表可以改进,它包含了历史上作为一个概念、模型和框架对密码分析有贡献的主要事件。

渗透工具和框架

本节涵盖了渗透测试过程中成功使用的几个渗透工具和框架。

我们将工具分为两类, Linux 黑客发行版渗透工具/框架。

  • Linux 黑客发行版

    • Kali Linux 代表了最先进的渗透测试平台之一。它可以安装在不同的设备上,可以用来攻击多种类型的设备。

    • BackBox 是一个非常强大的渗透测试发行版,包括强大的安全评估。

    • Parrot 安全 OS 是新发行的。它的设计和实现非常专业。它的目标是提供在线服务和其他类型服务的云环境。

    • BlackArch 是一个非常有趣的渗透测试平台和安全研究。它构建在 Arch Linux 之上。与 Arch Linux 一样,由于其复杂性和不同的安装说明,用户需要注意安装过程。

    • Bugtraq 是一个功能强大且易于使用的平台,包含一套重要的取证和渗透工具。

    • DEFT Linux ( D 数字 E 证据&ForensicsT工具套件)是一个计算机取证的平台。有可能将它作为一个活动系统运行。

    • Samurai Web 测试框架是一个强大的工具集合。它可用于网络渗透测试。它是一个虚拟机文件,可以安装在 VirtualBox 和 VMWare 中。

    • Pentoo Linux 建立在 Gentoo 之上。发行版的目标是提供快速的安全性和渗透测试分析。它以实时分发的形式提供。

    • CAINE(CcomputerAidedIninvestigativeEn environment)是一套复杂的工具,其中包含用于系统取证模块和分析的专业框架和模块。

    • 网络安全工具包是一个流行的工具和发行版。它很容易安装,可以作为 Fedora 上的一个实时 ISO 构建来完成。它有一套强大的开源网络安全工具。它有一个专业的 web 用户界面,提供有关网络和系统管理、网络监控工具和分析的重要细节。

    • Fedora Security Spin 是一个专业发行版,可用于安全审计和渗透测试。从工业界到学术界,各种专业人士都在使用它。

    • ArchStrike 是一个基于 Arch Linux 的测试发行版,可供安全领域的专业人士使用。

    • Cyborg Hawk 拥有 750 多种用于安全专业人员和执行渗透测试的工具。

    • Matriux 还是挺有前途的。它可以用于渗透测试、道德黑客、法医调查、漏洞分析等等。

    • Weakerth4n 在黑客或密码分析领域并不知名。它提供了一种独特的渗透测试方法,并且是使用 Debian (Squeeze)构建的。

  • 渗透工具/框架 (Windows 和 Linux 平台)

    • Wireshark 是一个非常著名的数据包嗅探器。它为网络包流量分析和通信协议分析提供了一套强大的工具。

    • Metasploit 是 pentesting 中使用的最重要的框架之一。

    • Nmap ( N 网络 M apper)是一款面向安全专业人士的专业网络发现和安全审计工具。该工具的目标是利用配置的目标。对于每个扫描的端口,我们可以看到安装了什么操作系统、什么服务正在运行、防火墙的详细信息等。

结论

这一章从总体上讨论了密码分析,涵盖了实用密码分析的基础、工具和工作方法。您现在应该具备以下知识:

  • 密码分析的任务和目标

  • 对历史上的事件以及有多少密码和算法影响了密码分析学科的快速概述

  • 主要术语的定义以及对不同类型黑客之间主要差异的清晰理解

  • 黑客和测试平台发行版的背景

  • 根据用户喜好的操作系统平台,理解独立使用的最重要的框架和渗透工具

文献学

  1. F.科恩,《密码学简史》,1990 年。新世界百科,2007 年。检索于 2009 年 5 月 4 日,来自 www.all.net/books/ip/Chap2-1.html

  2. 密码学。检索于 2009 年 5 月 4 日,来自 www.newworldencyclopedia.org/entry/Cryptography

  3. 米(meter 的缩写))Pawlan,“密码术:秘密信息的古代艺术”1998.检索于 2009 年 5 月 4 日,来自 www.pawlan.com/Monica/crypto/

  4. J.Rubin,Vigenere 密码,2008 年。检索于 2009 年 5 月 4 日,来自 www.juliantrubin.com/encyclopedia/mathematics/vigenere_cipher.html

  5. K.数论 1,2002。检索于 2009 年 5 月 4 日,来自 http://math.usask.ca/encryption/lessons/lesson00/page1.html

  6. 米(meter 的缩写))惠特曼和 H. Mattord,信息安全原则。凤凰城大学定制版电子文本。加拿大,汤姆森学习公司,2005 年。检索于 2009 年 5 月 4 日,来自 CMGT 凤凰城大学资源/432。

  7. 电码书。密码与密码破解秘史。西蒙·辛格,1999 年

  8. A.Ibraham,“Al-Kindi:密码学的起源:阿拉伯的贡献”,《密码学》,第 16 卷,第 2 期(第 97-126 页)。一九九二年四月。 www.history.mcs.st-andrews.ac.uk/history/Mathematicians/Al-Kindi.html

  9. Abu Yusuf yaqub ibn ishaq al-sabbah al-kindi, www.trincoll.edu/depts/phil/philo/phils/muslim/kindi.html

  10. 哲学家:亚库卜·伊本·伊扎克·肯尼迪日、k·金迪、阿布·优素福·亚库卜·伊本·伊沙克(草 866-73)。 www.muslimphilosophy.com/ip/kin.html

  11. Ahmad Fouad Al-Ehwany,穆斯林哲学史第 1 卷中的“Al-Kindi”(第 421-434 页)。新德里:低价出版物。1961.

  12. Ismail R. Al-Faruqi 和 Lois Lamya al-Faruqi,伊斯兰文化地图集,第 305-306 页。纽约:麦克米伦出版公司。1986.

  13. 《大英百科全书》(第 352 页)。芝加哥:威廉·本顿。1969.

  14. 奥康纳和罗伯逊、阿布·优素福·雅各布·伊本·伊斯哈格·萨巴·金迪。1999.**

十九、密码分析攻击和技术

这一章致力于最重要和最有用的密码分析和密码分析标准、验证方法、分类和密码分析攻击的操作。密码分析学科非常复杂,关于它的写作需要数千个研究小时。以下部分包含对您在日常活动中使用至关重要的最重要元素的调查。

标准

标准的重要性至关重要,任何专业人员在进行密码分析攻击时都应该知道。大多数密码分析攻击仅仅是为了商业目的。政府使用和商业目的之外的任何密码分析活动都是不合法的,并且不应该为了个人利益而进行。

组织非常容易受到安全攻击,确保组织满足有关其数据安全性的必要要求非常重要。任何组织都可以雇佣安全专家来执行密码分析攻击,以便测试其安全性并找到以后可能被恶意用户/攻击者利用的漏洞。

这些标准是由机构和组织提供的。它们包含密码学和密码分析方法、框架和算法。这些机构和组织是

  • IEFT 公钥基础设施(X.509) :该组织致力于互联网上使用的基于公钥系统的协议的标准化。

  • 国家标准与技术研究所(NIST) :该研究所专注于为美国政府制定 FIPS 标准。

  • 美国国家标准协会(ANSI) :其目标是维护来自私营部门的标准。

  • 互联网工程任务组(IEFT) :它代表了一个由网络、运营商、服务商和研究人员组成的国际社区。他们的主要目的是通过互联网架构的发展来体现的。

  • 电气和电子工程研究所(IEEE) :其目标是设计不同领域的理论和先进技术,如电子学、计算机科学和信息学。

  • 国际标准化组织(ISO) :它是一个非政府组织,包括 100 多个国家。其主要目标是鼓励标准化的发展,以帮助专业人士促进国际服务交流。

FIPS 140 比 2,FIPS 140 比 3,ISO 15408

1ISO 15408 是 IT 安全评估中最重要的标准之一,在国际上被用作参考系统标准。该标准包括 IT 领域的一系列规则和要求。目标是验证产品和加密系统的安全性。

*FIPS 140-2 和 140-3 提供了需要遵守的指南,以完成一组具体的技术要求,这些技术要求分为四个级别。

在为特定应用或加密模块开发规范或标准时,您需要考虑 FIPS 140-2/FIPS 140-3 和 ISO 15408 这两个标准。

基于标准开发的产品需要进行测试。测试的目标是获得验证,并确认标准得到了正确的遵循和尊重。

密码系统的验证

如果业务需要在软件和通信系统中实施密码分析和密码操作,则需要密码和密码分析服务。这些服务由认证机构授权,它们包括诸如数字签名生成和验证、加密和解密、密钥生成、密钥分发、密钥交换等功能。

图 19-1 中的模型是基于密码和密码分析模块进行安全性测试的通用模型。

表 19-1

对加密算法的攻击

|

对加密算法的攻击类型

|
| — |
|

攻击标题

|

攻击描述

|
| — | — |
| 已知明文攻击 | 密码分析者有一个加密的文本和对应的明文。这种攻击的目的是让密码分析人员从数据中分离出加密密钥。 |
| 选择文本攻击 | 密码分析者可以选择指出要加密的明文。通过使用这种类型的攻击,密码分析者可能试图从加密密钥中分离出文本信息,并有可能通过不同的方法访问加密算法或密钥。 |
| 密码-密文攻击 | 密码分析者保存相同的文本,该文本用明文及其对应的两个或更多不同的密钥加密。 |
| 分割和封锁攻击 | 密码分析者具有实现不同算法输入和输出之间的一组关联的能力,目的是分离不同的算法输入,这让他将问题分成两个或更多容易解决的问题。 |
| 线性综合征发作 | 密码分析方法包括设计和创建特定于伪随机发生器的线性方程组,并用加密文本验证该方程组,从而获得高概率明文。 |
| 一致性线性攻击 | 密码分析方法包括从模拟密钥开始创建特定于伪随机发生器的线性方程方案,并通过概率为 1 的伪随机发生器检查该方案,从而获得高概率明文。 |
| 随机攻击 | 这种攻击被称为预测攻击,如果生成器的输出是自相关的,并且密码分析者设法获得伪随机生成器的输出和加密文本作为输入数据,则这种攻击是可能的。这样就获得了明文。 |
| 信息线性攻击 | 也称为线性复杂度攻击,如果有任何机会使生成器与斐波那契算法相等,并且如果线性复杂度与低生成器相等,则攻击是可能的。利用这种类型的攻击,可以构造类似的算法和类似的密钥。 |
| 病毒攻击 | 如果应用加密,这种攻击是可能的算法并在易受攻击且未受保护的 PC 上运行。 |

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

图 19-1

验证和测试框架

对于充分的测试和验证过程,至少需要密码模块密码/密码分析算法 *。*对于开发的任何加密产品(或桌面/网络软件应用),有必要执行测试并将产品提交给 CMVP 2 (加密模块验证程序),以便根据 FIPS 140-2 3 和 FIPS 140-3 进行测试。 4

一个密码模块被表示为专用软件和硬件进程的组合。利用经验证的加密和密码分析模块的最重要的优势是

  • 模块应满足最低要求。

  • 应在标准范围内通知和指导授权人员和技术人员。该标准得到了普遍认可,并且经过了测试。

  • 在开发加密模块之前,验证最终用户是否知道加密模块已经根据安全要求进行了验证和测试。

  • 为了开发类似和特定的应用,需要实现高水平的安全性可靠性。

特征 FIPS 140-2 的安全要求具有 11 个可在加密模块的设计和实现过程中使用的度量和标准。加密模块必须满足并验证每个指标。在验证过程中,从 1 到 4 的标记被分配给加密模块,与所保证的安全级别成比例。

加密模块通过验证后,应包含一组信息,如制造商名称、地址、模块名称、模块版本、模块类型(软件或硬件)、验证日期、验证级别和模块描述。

密码分析操作

设计加密系统时,应遵循以下原则。这些原则很简单,应该构成任何密码分析程序的基础:

  • 不应该低估对手。

  • 密码系统可以由密码分析人员来评估。

  • 在评估密码系统之前,对手对被评估的密码系统的了解被考虑在内。

  • 密码系统的保密性依赖于密钥。

  • 在加密系统评估过程中,必须考虑系统中的所有元素,如密钥分发、加密内容等。

Claude Shannon 认为,在进行密码系统评估时,必须考虑以下标准:

  • 一旦消息被成功解密,密码分析者将获得一份奖品。

  • 密钥长度和复杂性

  • 加密-解密过程的复杂程度

  • 根据文档大小的编码文本的大小

  • 传播错误的方式

每个密码都有一个解决方案的基本操作如下:

  • 找到并决定使用的词汇

  • 决定加密系统

  • 加密系统的单个密钥的重建或加密流系统的部分或完全重建

  • 这种方案的重构或确定完全明文

密码分析攻击的分类

本节讨论针对密码算法、密钥、认证协议、系统本身的攻击类型,以及硬件攻击。

对密码算法的攻击

表 19-2 列出了对加密算法最常见的攻击。

表 19-2

对密钥的攻击

|

对密钥的攻击类型

|
| — |
|

攻击标题

|

攻击描述

|
| — | — |
| 暴力攻击 | 这种攻击需要对密钥和密码进行严格的检查,如果加密密钥的大小和加密密钥的空间很小,这种攻击就有可能发生。 |
| 智能暴力攻击 | 加密密钥的随机性程度小(熵小),这使得密码可以被识别,因为它接近于所使用的语言术语。 |
| 回溯攻击 | 这种攻击是基于实现一种回溯方法,这种方法包括在期望的方向上继续搜索的条件的存在。 |
| 贪婪攻击 | 攻击提供了最佳本地密钥(最佳全局密钥不能相同)。 |
| 字典攻击 | 这种攻击包括搜索密码或密钥,并使用字典来执行。 |
| 混合字典攻击 | 这种攻击是通过改变字典中的术语并借助字典中的单词通过暴力初始化攻击来实现的。 |
| 病毒攻击 | 如果密钥存储在未受保护的 PC 上,这种攻击是可能的。 |
| 密码哈希攻击/密钥 | 如果密码哈希设计不当或不正确,就会发生这种攻击。 |
| 替代攻击 | 原始密钥由第三方替换,并在网络中重复。这可以通过病毒来实现。 |
| 存储加密密钥 | 如果这是在没有任何物理保护措施或密码、软件或硬件的情况下以错误的方式(与加密数据一起)在明文中完成的,这可能导致对加密消息的攻击。 |
| 旧加密密钥的存储 | 该攻击将导致旧加密文档的受损版本。 |
| 关键妥协 | 如果对称密钥被泄露,那么只有分配给该键的文档将会受到威胁。如果可以发现存储在各种服务器上的公钥被泄露,那么攻击者就可以替换数据的合法所有者,从而在网络内造成不良的负面影响。 |
| 万能钥匙 | 密码系统代表不同的阶段。 |
| 密钥寿命 | 它是一个不可或缺的组成部分,排除了尚未检测到的成功攻击的可能性。 |

对密钥的攻击

表 19-2 列出了对密钥最常见的攻击。

对认证协议的攻击

认证协议受到各种形式的攻击。我们在表 19-3 中列出了最相关的,常用的。考虑到网络认证协议非常必要且至关重要,这一点非常重要。一旦遭到破坏,就有可能暴露至关重要的信息,攻击者可以获得大量信息。

表 19-3

对认证协议的攻击

|

对认证协议的攻击类型

|
| — |
|

攻击标题

|

攻击描述

|
| — | — |
| 对公钥的攻击 | 协议内的攻击是为了签名而发生的。它仅适用于公钥方案。 |
| 对称算法的攻击 | 在认证协议内部,攻击必须发生在签名上。这只能通过使用对称密钥来实现。 |
| 被动攻击 | 入侵者可以拦截并跟踪接触在没有任何干扰的情况下。 |
| 使用第三人称攻击 | 两个伙伴在通信信道内的通信被第三方用户故意截取。 |
| 失败停止签名 | 这是一种加密协议,发送者可以提供他的签名是否是伪造的证据。 |

结论

这一章涵盖了适用于密码分析的最重要和最有用的指南和方法。要检查和验证加密和密码分析算法和方法的实现,您必须能够处理标准。你了解到了

  • 密码分析攻击的分类

  • 密码分析过程中涉及的操作

  • FIPS 140-2 和 FIPS 140-3 标准

  • ISO 15408 标准

  • 加密系统验证过程

文献学

  1. Adrian Atanasiu, 密码学中的数学 。美国出版社,编辑:科学宇宙,ISBN:978-973-1944-48-7。2015.

  2. Adrian Atanasiu, Information Security vol 1Cryptography) , InfoData 出版社, ISBN: 978-973-1803-18-0.2007.

  3. Adrian Atanasiu, Information Security vol 2 (Security Protocols) , InfoData 出版社, ISBN: 978-973-1803-18-0.2009.

  4. S.J. Knapskog,“安全通信协议的形式规范和验证”(第 58–73 页)。 https://link.springer.com/chapter/10.1007/BFb0030352

  5. K.Koyama,“破解公钥密码系统能力的直接演示”(第 14-21 页)。 www.iacr.org/cryptodb/data/paper.php?pubkey=279

  6. P.J. Lee *,“*公共网络的安全用户访问控制”(第 46–57 页)。 www.sciencedirect.com/science/article/pii/S0140366416300652

  7. R.Lidl 和 W.B. Muller,“关于强斐波那契伪素数的注记”(第 311–317 页)。 https://link.springer.com/article/10.1007/BF01810848

  8. 阿尔弗雷德·j·梅内塞斯和斯科特·范斯通,“椭圆曲线密码系统的实现”(第 2-13 页)。 https://link.springer.com/article/10.1007/BF00203817

  9. M.J. Mihaljevi 和 J.D. Goli,“给定噪声输出序列时移位寄存器初始状态重建的快速迭代算法”(第 165–175 页)。密码学进展—AUSCRYPT '90,计算机科学讲义,第 453 卷,施普林格出版社,柏林,1990 年。

ISO 15408 .链接: www.iso.org/standard/50341.html

2

CMVP, https://csrc.nist.gov/projects/cryptographic-module-validation-program

3

FIPS 140-2、 https://csrc.nist.gov/publications/detail/fips/140/2/final

4

FIPS 140-3、 https://csrc.nist.gov/publications/detail/fips/140/3/final

*

二十、线性和差分密码分析

在本章中,我们将介绍两种重要的密码分析类型,线性和*差分密码分析,*介绍关于这两种密码分析如何进行和实现的基本和高级概念和技术。

关于线性和差分密码分析的研究文献在理论方法和机制方面是广泛和丰富的,但是只有少数方法可以在现实环境中实际应用。理论密码分析和应用密码分析之间的差异是巨大的,发表的许多观点(算法、方法、博弈论方面等。)在过去的 12 年里将研究人员和专业人士引入了歧途。对密码分析进行研究并增加其在实践和不同场景中应用的潜在价值需要时间、经验以及理论家和实践者之间的持续交叉合作,而这两种类型之间没有任何隔离。

它们的重要性在密码分析领域至关重要,为构造分组密码和流密码的密码分析攻击方案提供了必要的工具和机制。

差分密码分析

差分密码分析是由 E. Biham 和 A. Shamir 在 20 世纪 90 年代早期提出的。差分密码分析的目标是测试密钥中的某些位置是否比密码中的其他位置更容易被追踪到。这个测试可以在任何一级风险下进行。实际上,这个测试是一个更复杂的测试过程的二阶近似。

通过差分密码分析,我们可以暴露密码算法的弱点。下面的差分密码分析的例子是针对流密码算法 来说明的。

该算法的伪代码如下:

  1. α←读取拒绝率

  2. Build n sets of perturbed keys starting from the key K.

    )

INPUT:    A base key is chosen as K = (k1,, kn) with ki ∈ {0, 1}
OUTPUT:   The sensitive and weak points of the cryptography
          algorithm and the resistance decision for
          differential cryptanalysis

)

对于 I,j=1,…,n,这样,第 I 个密钥是通过改变第 I 个的位从基密钥获得的。

  1. 建筑密码。我们将从基本密钥、扰动密钥和明文 M 开始构建 n + 1 个密码。我们将用C(I), i = 1,…, n + 1 来标注这个密文。作为明文,我们可以在任何地方选择文本 0。

  2. Building the correlation matrix. In this step we will build the matrix (n + 1) × (n + 1) for the corellation values C:

    )

其中 correlationcij表示应用于序列的统计测试的值(密文 i密文 j )。矩阵 C 被表示为在主对角线上具有 1 的对称矩阵。

  1. The computation of significant value. It will count the values of significant correlation which are situated above the main diagonal. A value is called significant if

    )

考虑 T 代表共循环测试中剔除数量的有效值的数量。

  1. Decision and result interpretation. If

    )

一旦计算出来,我们就可以判定对差分密码分析的不抵抗性()和)分别代表)和)阶正态分布的分位数,并将 ij 元素固定为nI>j≥1,其中cij有意义)。这些元素代表了算法的弱点。否则,我们将无法提及任何关于抵抗这类攻击的东西。

清单 20-1 中的 C# 源代码是上述伪代码的实现(输出见图 20-1 )。

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

图 20-1

差异密码分析示例

using System;

namespace DifferentialCryptanalysis
{
    class ExampleOfDifferentialCryptanalysis
    {
        //** variables
        public static int[] Known_P0 = new int[10000];
        public static int[] Known_P1 = new int[10000];
        public static int[] Known_C0 = new int[10000];
        public static int[] Known_C1 = new int[10000];
        public static int Good_P0, Good_P1, Good_C0, Good_C1;
        public static int numbers_pairs;
        public static int[] characters_data0 = new int[16];
        public static int characters_data_max = 0;
        public static int[,] characters = new int[32, 32];

        public static int[] theSBOX = new int[16] { 3, 14, 1,
                10, 4, 9, 5, 6, 8, 11, 15, 2, 13, 12, 0, 7 };
        public static int[] sbox_reviwed = { 14, 2, 11, 0, 4,
                6, 7, 15, 8, 5, 3, 9, 13, 12, 1, 10 };

        public static int round_function(int theInputData, int theKey)
        {
            return theSBOX[theKey ^ theInputData];
        }

        public static int encryption(int theInputData, int k_0, int k_1)
        {
            int x_0 = round_function(theInputData, k_0);
            return x_0 ^ k_1;
        }

        public static void find_differences()
        {
            Console.WriteLine("\nGenerating a differential
                                table structure for XOR:\n");

            Random rnd = new Random();

            int x, y;

            for (x = 0; x < 16; x++)
            {
                for (y = 0; y < 16; y++)
                {
                    characters[x ^ y, theSBOX[x] ^ theSBOX[y]]
                                                    = rnd.Next(-1, 1);
                }
            }

            for (x = 0; x < 16; x++)
            {
                for (y = 0; y < 16; y++)
                {
                    characters[x^y, theSBOX[x] ^
                                                theSBOX[y]]++;
                }
            }

            for (x = 0; x < 16; x++)
            {
                for (y = 0; y < 16; y++)
                    Console.Write("{0}",
                                            characters[x, y] + " ");
                Console.WriteLine("\n");
            }

            Console.WriteLine("\nShow the possible differentials:\n”);

            for (x = 0; x < 16; x++)
                for (y = 0; y < 16; y++)
                    if (characters[x, y] == 6)
                        Console.WriteLine("\t\t6/16: {0} to
                                                    {1}\n", x, y);
        }

        public static void genCharData(int input_differences,
                                       int output_differences)
        {
            Console.WriteLine("\nValues represented as
                        possible intermediate based on
                        differntial has been generated: ({0} to
                        {1}):\n", input_differences,
                        output_differences);

            characters_data_max = 0;
            int p;

            for (p = 0; p < 16; p++)
            {
                int theComputation = p ^ input_differences;

                if ((theSBOX[p] ^ theSBOX[theComputation]) ==
                                                    output_differences)
                {
                    Console.WriteLine("\t\tThe certain values
                    choosen are:   {0} + {1} to  {2} +
                    {3}\n", p, theComputation, theSBOX[p],
                    theSBOX[theComputation]);

                    characters_data0[characters_data_max] = p;
                    characters_data_max++;
                }
            }
        }

        public static void genPairs(int input_differences)
        {
            Random randomNumber = new Random();

            Console.WriteLine("\nGenerating {0} known pairs
                          with input differential of {1}.\n",
                          numbers_pairs, input_differences);

            //** generate randomly subkey
            int Real_K0 = randomNumber.Next() % 16;

            //** generate randomly subkey
            int Real_K1 = randomNumber.Next() % 16;

            Console.WriteLine("\t\tThe K0 Real Value is =
                                                    {0}\n", Real_K0);
            Console.WriteLine("\t\tThe K1 Real Value is =
                                                    {0}\n", Real_K1);

            int b;

            //** Generate plaintexts pairs using different
            //** XORs based on the differences
            //** that are provided as input
            for (b = 0; b < numbers_pairs; b++)
            {
                Known_P0[b] = randomNumber.Next() % 16;
                Known_P1[b] = Known_P0[b] ^ input_differences;
                Known_C0[b] = encryption(Known_P0[b], Real_K0,
                                                      Real_K1);
                Known_C1[b] = encryption(Known_P1[b], Real_K0,
                                                      Real_K1);
            }
        }

        public static void findGoodPair(int
                                             output_differences)
        {
            Console.WriteLine("\nSearching for good pair:\n");

            int c;
            for (c = 0; c < numbers_pairs; c++)
                if ((Known_C0[c] ^ Known_C1[c]) ==
                                                    output_differences)
                {
                    Good_C0 = Known_C0[c];
                    Good_C1 = Known_C1[c];
                    Good_P0 = Known_P0[c];
                    Good_P1 = Known_P1[c];
                    Console.WriteLine("\t\tA good pair has
                                been found: (P0 = {0}, P1 = {1}) to
                                (C0 = {2}, C1 = {3})\n", Good_P0,
                                Good_P1, Good_C0, Good_C1);
                    return;
                }
            Console.WriteLine("There is no pair proper
                                                        found!\n");
        }

        public static int testKey(int Test_Key_0,
                                                  int Test_Key_1)
        {
            int c;
            int someCrappyValue = 0;
            for (c = 0; c < numbers_pairs; c++)
            {
                if ((encryption(Known_P0[c], Test_Key_0,
                          Test_Key_1) != Known_C0[c]) ||
                          (encryption(Known_P1[c], Test_Key_0,
                          Test_Key_1) != Known_C1[c]))
                {
                    someCrappyValue = 1;
                    break;
                }
            }

            if (someCrappyValue == 0)
                return 1;
            else
                return 0;
        }

        public static void crack()
        {
            Console.WriteLine("\nUsing brute force to reduce
                                                    the keyspace:\n");

            for (int g = 0; g < characters_data_max; g++)
            {
                int Test_K0 = characters_data0[g] ^ Good_P0;

                int Test_K1 =
                          theSBOX[characters_data0[g]] ^ Good_C0;

                if (testKey(Test_K0, Test_K1) == 1)
                    Console.WriteLine("\t\tThe Key is! ({0},
                                      {1})\n", Test_K0, Test_K1);
                else
                    Console.WriteLine("\t\t({0}, {1})\n",
                                             Test_K0, Test_K1);
            }
        }

        static void Main(String[] args)
        {
            Console.WriteLine("DIFFERENTIAL CRYPTANALYSIS\n");
            Random randomPerRunning = new Random();
            //** generating random values per each running
            randomPerRunning.Next();

            //** identify proper differentials
            //** within the SBoxes
            find_differences();

            //** defining a numerical
            //** value for known pairs
            numbers_pairs = 8;

            //** identify data inputs that will help
            //** to lead us to specific characteristic
            genCharData(4, 7);

            //** randomly, generate pairs of
            //** chosen-plaintext
            genPairs(4);

            //** based and using the characteristic,
            //** we will choose a known pair
            findGoodPair(7);

            //** use characteristic_data0 and within
            //** the proper pair we will find it
            crack();

            while (true) { }
            Console.ReadKey();
        }
    }
}

Listing 20-1Implementation of Differential Cryptanalysis Example

线性密码分析

线性密码分析作为 DES(数据加密系统)的理论框架于 1993 年被设计和引入。目前,线性密码分析被用于分组密码中,并且代表了设计和实施复杂攻击的一个非常好的起点。

我们可以将线性密码分析定义为在密钥、明文结构和密文结构之间建立的线性关系。明文的结构用字符或位来表示。有必要将其表示为一个以异或为特征的操作链,显示为

)

其中⨁表示异或运算(这是一种二进制运算), A i 表示从 i th 位置开始输入的位结构a=a1A 2 ,…】, B j 代表输出结构B=B1B 2 、…】和 k

进行线性密码分析

在大多数情况下,我们从这样的想法出发,即除了私钥之外,我们知道加密算法。在分组密码上启动线性密码分析被表示为模型/框架,描述为

  • 识别特征加密算法的非线性分量的线性近似(例如,S 盒)。

  • 执行替换盒的线性近似之间的组合,其包括在加密算法内执行的操作。对于专业人员来说,关注线性近似是非常重要的,因为它代表了一个特殊的函数,该函数包含并处理明文和密文比特以及来自私钥的比特。

  • 设计线性近似作为第一次使用的键的指南。这将非常有帮助,因为它为所有可能的键值节省了重要的计算资源。使用多重线性近似对于消除尝试所必需的关键数字是非常有用的。

在下一节中,我们将提供一些细节,以帮助确定在进行线性密码分析攻击时应该考虑哪些组件。如果不在理论层面理解以下概念,将很难实施任何攻击。

s 盒

通过 S 盒,非线性与它的操作、异或和位移一起被引入,它们也在线性表示中被发现。

S-Box 的目标是在具有特定输出的输入二进制序列之间创建一个映射。也就是说,我们将提供非线性,这将建立和呈现应用线性密码分析时获得的仿射近似。表 20-1 显示了一个 S-Box 的例子以及映射是如何工作的。它使用第 1 个和第 4 个位来查找列和中间位,第 3 个和第 4 个*。基于此,以输入 1110 将是 0101 的方式确定行。*****

**表 20-1

S-Box 的例子

|   |

11

|

10

|

01

|

00

|
| — | — | — | — | — |
| 00 | "0000" | "0001" | "0010" | "0011" |
| 01 | "1000" | "1001" | "1111" | "1011" |
| 10 | "1100" | "1101" | "1110" | "1010" |
| 11 | "0100" | "0101" | "0010" | "0111" |

表 20-2 显示了作为输入的位和作为输出的位的例子之间的映射操作。

表 20-2

输入和输出之间的映射

|

The Input (J)

|

The Output (Q)

|
| — | — |
| "0000" | "0011" |
| "0001" | "0010" |
| "0010" | "1011" |
| "0011" | "1111" |
| "0100" | "1010" |
| "0101" | "1110" |
| "0110" | "0111" |
| "0111" | "0010" |
| "1000" | "0001" |
| "1001" | "0000" |
| "1010" | "1001" |
| "1011" | "1000" |
| "1100" | "1101" |
| "1101" | "1100" |
| "1110" | "0101" |
| "1111" | "0100" |

S-Box 线性近似

我们将从我们想要近似上面提出的替换框的结构的想法开始。基于这些信息,我们得到了各种线性近似的精度,这是相当高的。我们包括具有以下形式的 256 个这样的线性近似:

)

其中 J 1Q i 代表第Ith位特征为输入( J )和输出( Q )对应于 d ig 举个例子,让我们用下面的线性近似法j2=q1q4并由 d = 0100 2g = 1001 2 给出。

线性逼近的串联

是时候进入下一步,为整个系统形成、设计和规划线性近似。为了实现这一点,我们需要两样东西:

  • 首先,我们需要已经计算出构成系统的每个组分的线性近似。

  • 第二,为了进行组合,我们简单地通过在不同的组合中使用异或来对整个方程组求和。这样,我们得到一个方程,它将消除中间变量。

组合两个变量

让我们考虑一下 B 1B 2 ,两个随机二元变量。它们之间的线性关系是b1⨁b2= 0。接下来,我们用 l 表示概率B1= 0,用 m 表示概率B2= 0。基于这两个随机自变量,我们有

)

继续向前,我们可以展示如下:

)

)

)

)

下一步通过计算b1⨁b2= 0 的偏差来表示。给出为ζ1ζ2

现在是用 C# 实现线性密码分析(见图 20-2 )的时候了(见清单 20-2 ),并展示如何在实践中使用上述概念。

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

图 20-2

线性密码分析输出模拟程序

using System;

namespace LinearCryptanalysis
{
    class ExampleOfLinearCryptanalysis
    {
        #region Variables
        public static int[,] approximation_table =
        new int[16,16];
        public static int[] known_plaintext = new int[500];
        public static int[] known_ciphertext = new int[500];
        public static int number_known = 0;

        public static int[] theSBox =
               new int [16] {9, 11, 12, 4, 10, 1, 2, 6, 13,
                                 7, 3, 8, 15, 14, 0, 5};
        public static int[] revtheSBox = {14, 5, 6, 10, 3, 15,
                                 7, 9, 11, 0, 4, 1, 2, 8, 13, 12};
        #endregion

        //** the function will round
        //** the sbox values accordingly
        //** based on the value inputed and the sub key
        public static int RoundingFunction(int theInputValue,
                                                int theSubKey)
        {
            int index_position = theInputValue ^ theSubKey;
            return theSBox[index_position];
        }

        //** generatiing the keys
        //** and generating the known pairs
        public static void FillingTheKnowledgedOnces()
        {
            Random randomNumber = new Random();
            int theSubKey_1 = randomNumber.Next() % 16;
            int theSubKey_2 = randomNumber.Next() % 16;

            Console.WriteLine("Generating the data: Key1 =
                  {0}, Key2 = {1}\n", theSubKey_1, theSubKey_2);

            for (int h = 0; h < number_known; h++)
            {
                known_plaintext[h] = randomNumber.Next() % 16;
                known_ciphertext[h] =
                          RoundingFunction(RoundingFunction(
                          known_plaintext[h], theSubKey_1),
                                theSubKey_2);
            }

            Console.WriteLine("Generating the data: Generating
                              {0} Known Pairs\n\n", number_known);
        }

        //** show the the linear approximation
        //** note that the parameters
        //** a and b starts from 1
        public static void DisplayTheApproximation()
        {
            Console.WriteLine("Generate the linear
                                            approximation: \n");

            for (int a = 1; a < 16; a++)
            {
                for (int b = 1; b < 16; b++)
                {
                    if (approximation_table[a, b] == 14)
                        Console.WriteLine("{0} : {1} to
                                {2}\n", approximation_table[a, b],
                                a, b);
                }
            }
            Console.WriteLine("\n");
        }

        public static int ApplyingTheMask(int v, int m)
        {
            //** v - is the value
            //** m - is the mask
            int internal_value = v & m;
            int total_amount = 0;

            while (internal_value > 0)
            {
                int temporary = internal_value % 2;
                internal_value /= 2;

                if (temporary == 1)
                    total_amount = total_amount ^ 1;
            }
            return total_amount;
        }

        //** the function will validate and
        //** test the keys accordingly
        public static void ValidationAndTestingKeys(int key_1,
        int key_2)
        {
            for (int h = 0; h < number_known; h++)
            {
                if (RoundingFunction(RoundingFunction
                          (known_plaintext[h], key_1), key_2) !=
                          known_ciphertext[h])
                break;
            }
            Console.WriteLine("* ");
        }

        public static void FindingTheApproximation()
        {
            Random randomNumber = new Random();

            //** The output the mask
            for (int a = 1; a < 16; a++)
            {
                //** The input mask
                for (int b = 1; b < 16; b++)
                {
                    //** the input
                    for (int c = 0; c < 16; c++)
                    {
                        if (ApplyingTheMask(c, b) ==
                            ApplyingTheMask(theSBox[c], a))
                        {
                            approximation_table[b, a]++;
                        }
                    }
                }
            }
        }

        public static void Main(String[] args)
        {
            int[] key_score = new int[16];
            int[] theProperKeys = new int[16];
            int stateProgress = 0;
            int maximum_score = 0;
            int guessing_key_1, guessing_key_2;
            int x, y;

            Random randomNumber = new Random();

            Console.WriteLine("Linear Cryptanalysis
                                        Simulation Program\n");

            randomNumber.Next();

            FindingTheApproximation();
            DisplayTheApproximation();

            int approximationAsInput = 11;
            int approximationAsOutput = 11;

            number_known = 16;
            FillingTheKnowledgedOnces();

            Console.WriteLine("Cryptanalysis Linear Attack –
                          PHASE1\. \n\t\t Based on linear
                          approximation = {0} -> {1}\n",
                          approximationAsInput,
                          approximationAsOutput);

            for (x = 0; x < 16; x++)
            {
                key_score[x] = 0;

                for (y = 0; y < number_known; y++)
                {
                    stateProgress++;

                    //** Find Bi by guessing at K1
                    int middle_round =
                          RoundingFunction(known_plaintext[y], x);

                    if ((ApplyingTheMask(middle_round,
                              approximationAsInput) ==
                              ApplyingTheMask(known_ciphertext[y],
                              approximationAsOutput)))
                          key_score[x]++;
                    else
                        key_score[x]--;
                }
            }

            for (x = 0; x < 16; x++)
            {
                int theScore = key_score[x] * key_score[x];
                if (theScore > maximum_score)
                    maximum_score = theScore;
            }

            for (y = 0; y < 16; y++)
                theProperKeys[y] = -1;

            y = 0;

            for (x = 0; x < 16; x++)
                if ((key_score[x] * key_score[x]) ==
                                                    maximum_score)
                {
                    theProperKeys[y] = x;
                    Console.WriteLine("Cryptanalysis Linear
                                Attack - PHASE 2\. \n\t\t The
                                possible for Key 1 = {0}\n",
                                theProperKeys[x]);
                    y++;
                }

            for (y = 0; y < 16; y++)
            {
                if (theProperKeys[y] != -1)
                {
                    int testing_key_1 =
                                RoundingFunction(known_plaintext[0],
                                theProperKeys[y]) ^
                                revtheSBox[known_ciphertext[0]];

                    int g;
                    int wrong = 0;
                    for (g = 0; g < number_known; g++)
                    {
                        stateProgress += 2;
                        int testOut =
                                RoundingFunction(RoundingFunction(
                                known_plaintext[g], theProperKeys[y]), testing_key_1);

                        if (testOut != known_ciphertext[g])
                            wrong = 1;
                    }
                    if (wrong == 0)
                    {
                        Console.WriteLine("Cryptanalayis
                                      Linear Attack - PHASE 3.\n");
                        Console.WriteLine("\t\tI have found
                                      the keys! Key1 = {0}, Key2 =
                                      {1}\n", theProperKeys[y],
                                      testing_key_1);

                        guessing_key_1 = theProperKeys[y];
                        guessing_key_2 = testing_key_1;
                        Console.WriteLine("Cryptanalysis
                                      Linear Attack - PHASE 4.\n");
                        Console.WriteLine("\t\tThe number of
                                      computation until the key has
                                      been found = 0\n",
                                      stateProgress);

                        }
                }
            }

            Console.WriteLine("Cryptanalyis Linear Attack –
                                                   PHASE 5.\n");
            Console.WriteLine("The number of computation =
                                      {0}\n\n", stateProgress);

            stateProgress = 0;

            for (y = 0; y < 16; y++)
            {
                for (x = 0; x < 16; x++)
                {
                    int t;
                    int wrong = 0;
                    for (t = 0; t < number_known; t++)
                    {
                        stateProgress += 2;
                        int testOut =
                               RoundingFunction(RoundingFunction(
                                      known_plaintext[t], y), x);

                        if (testOut != known_ciphertext[t])
                            wrong = 1;
                    }
                    if (wrong == 0)
                    {
                        Console.WriteLine("Brute Force –
                                                         PHASE 1.\n");
                        Console.WriteLine("\t\tI managed to
                                      find the keys! \n\t\t
                                            Key1 = {0} \n\t\t Key2 =
                                            {1}\n", y, x);

                        Console.WriteLine("Brute Force –
                                                         PHASE 2\n");
                        Console.WriteLine("\t\tThe number of
                                      computations until the key
                                      was dound = {0}\n",
                                      stateProgress);
                    }
                }
            }

            Console.WriteLine("Brute Force - PHASE 3.\n");
            Console.WriteLine("Computations total_amount =
                                              {0}\n", stateProgress);

            while (true) { }
        }
    }
}

Listing 20-2Linear Cryptanalysis Simulation

结论

在本章中,我们讨论了差分和线性密码分析攻击,以及如何设计和实现这种攻击。我们介绍了在设计这种密码分析攻击之前必须了解的理论背景和主要基础。

在本章结束时,您现在可以

  • 从理论上确定密码分析人员应该关注的主要部分

  • 了解这些组件有多脆弱以及如何被利用

  • 实现线性和差分密码分析攻击

文献学

  1. 琼·代蒙、拉斯·努森和文森特·里门,《分组密码方阵》。快速软件加密(FSE),”计算机科学讲义第 1267 卷(第 149-165 页),以色列海法:施普林格出版社。citeserx 10 . 1 . 1 . 55 . 6109。1997.

  2. H.Heys,“线性和差分密码分析教程”,载于 Cryptologia ,第二十六卷,第 3 期(第 189-221 页),2002 年。

  3. 米(meter 的缩写))Matsui,“DES 密码的线性密码分析方法”,载于密码学进展-EUROCRYPT’93(第 386-397 页),Springer-Verlag,1994 年。

  4. E.比哈姆,《论松井的线性密码分析》在 a .德森蒂斯峰(编),计算机科学讲座笔记,第 950 卷,(第 341–355 页)。施普林格出版社,柏林,1995。

  5. A.Biryukov,C. De Cannière,M. Quisquater,“论多重线性近似”,M. Franklin(编辑),密码学进展,2004 年加密会议录,计算机科学讲义 3152 (第 1-22 页)。斯普林格出版社,2004 年。

  6. 长度 Keliher,H. Meijer 和 S.E. Tavares,“SPN 最大平均线性外壳概率上限的新方法”在 b .普菲兹曼(编), LNCS ,第 2045 卷(第 420—436 页)。施普林格出版社,柏林,2001。

  7. 长度 R. Knudsen 和 J.E. Mathiassen,“对 DES 的选择明文线性攻击”。),计算机科学讲义,1978 卷(第 262–272 页)。施普林格出版社,柏林,2001。

  8. 米(meter 的缩写))FEAL 密码已知明文攻击的新方法在 R.A. Rueppel(编),计算机科学讲义,第 658 卷(第 81-91 页)。施普林格出版社,柏林,1993。

  9. 米(meter 的缩写))数据加密标准的首次实验性密码分析。在 Y.G. Desmedt (ed),计算机科学讲义,第 839 卷(第 1-11 页)。施普林格出版社,柏林,1994。**

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值