简体   繁体   English

使用Eigen C ++库反转矩阵mod-26

[英]Inverting matrices mod-26 with Eigen C++ library

I'm trying to write a program to crack a Hill cipher of arbitrary dimensions (MxM) in C++. 我正在尝试编写一个程序来破解C ++中任意尺寸(MxM)的希尔密码。 Part of the process requires me to calculate the mod-26 inverse of a matrix. 该过程的一部分要求我计算矩阵的mod-26逆。

For example, the modular inverse of 2x2 array 例如,2x2数组的模逆

14 3 11 0 14 3 11 0

is

0 19 9 24 0 19 9 24

I have a function that can accomplish this for 2x2 arrays only, which is not sufficient. 我有一个函数只能对2x2数组完成此操作,这还不够。 I know that calculating inverses on larger-dimension arrays is difficult, so I'm using the Eigen C++ library. 我知道很难在大维数组上计算逆,因此我使用的是Eigen C ++库。 However, the Eigen inverse() function gives me this as the inverse of the above matrix: 但是,Eigen inverse()函数为我提供了上述矩阵的逆函数:

0.000 0.091 0.333 -0.424 0.000 0.091 0.333 -0.424

How can I calculate the modular 26 inverse that I need for a matrix of any dimensions with Eigen? 如何使用Eigen计算任何尺寸的矩阵所需的模数26逆数?

Try this: 尝试这个:

#include <iostream>
#include <functional>
#include <Eigen/Dense>

using namespace Eigen;                                                                                       
using namespace std;                                                                                         

int inverse_mod_26(int d)                                                                                    
{                                                                                                            
   // We're not going to use Euclidean Alg. or                                                               
   // even Fermat's Little Theorem, but brute force                                                          
   int base = 26, inv = 1;                                                                                   

   while ( (inv < base) &&                                                                                   
       (((d * ++inv) % 26) != 1)) {}                                                                         

   return inv;                                                                                               
}                                                                                                            

int main(int argc, char **argv)                                                                              
{                                                                                                            

   Matrix2d m, minv;                                                                                         
   int inv_factor;                                                                                           
   m << 14, 3, 15, 0;                                                                                        
   double mdet = m.determinant();                                                                            

   minv = mdet * m.inverse();                                                                                
   transform(&minv.data()[0], &minv.data()[4], &minv.data()[0],                                              
         [](double d){ return static_cast<int>(d) % 26;});                                                   
   if ((static_cast<int>(mdet) % 26) == 1) { // no further modification}                                     
   else                                       
     {                                                                                                       
        inv_factor = inverse_mod_26(std::abs((m * minv)(0,0)));                                              
        if (inv_factor == 26)                                                                                
          {                                                                                                  
             cerr << "No inverse exists!" << endl;                                                           
             return EXIT_FAILURE;                                                                            
          }                                                                                                  

        transform(&minv.data()[0], &minv.data()[4], &minv.data()[0],                                         
              [=](double d){ return static_cast<int>(d) * inv_factor;});                                     
     }                                                                                                       

   cout << "m = " << endl << m << endl;                                                                      
   cout << "minv = " << endl << minv << endl;                                                                
   cout << "(m * minv) = " << endl << m * minv << endl;                                                      

   return 0;                                                                                                 
}                            

This is a 2x2 case, for base 26, but can easily be modified. 对于底座26,这是2x2的情况,但可以轻松修改。 The algorithm relies on modifying the normal matrix inverse, and can easily be explained, if you wish. 该算法依赖于修改法线矩阵逆,并且,如果您愿意,可以很容易地解释。 If your original matrix has determinant (in the normal sense) that is not relatively prime to 26; 如果您的原始矩阵的行列式(通常意义上)不是26的素数; ie, if GCD(det(m), 26) != 1 , then it will not have an inverse. 也就是说,如果GCD(det(m), 26) != 1 ,那么它将没有逆。

Tip: to avoid this problem, and the else clause above, pad your dictionary with three arbitrary characters, bringing the size to 29, which is prime, and will trivially satisfy the GCD property above. 提示:为避免此问题,请使用上面的else子句,在字典中填充三个任意字符,将大小设为29(即质数),并会轻松满足上述GCD属性。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM