bling_yu

An Improved Method for Predicting Truncated Fibonacci LFSRs over Integer Residue Rings

Mar 13th, 2025 (edited)
576
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 10.98 KB | None | 0 0
  1. // This code is used to recover the truncated ZUC's driving sequence.
  2. // The library used is the NTL 11.4.3 library.
  3. // The whole experimental process consists of 4 steps. Searching linear relations, Recovering the modulus, the coefficients and the initial states.
  4.  
  5. #include <NTL/vec_ZZ.h>
  6. #include <NTL/mat_ZZ.h>
  7. #include <NTL/mat_ZZ_p.h>
  8. #include <NTL/ZZ_pX.h>
  9. #include <NTL/ZZX.h>
  10. #include <NTL/LLL.h>
  11. #include <fstream>
  12. #include <ctime>
  13. #include <math.h>
  14. #include <chrono>
  15. #include <fstream>
  16. NTL_CLIENT
  17. using namespace std;
  18.  
  19. // Search polynomials that annihilate the sequence a
  20. // The high-order scenario
  21. // The modulus m is known
  22. mat_ZZ Search_linear_relations_high_m(ZZ m, vec_ZZ y, int beta, int r, int t)
  23. {
  24.     auto start = std::chrono::high_resolution_clock::now();
  25.     mat_ZZ L, C;
  26.     int i, j;
  27.  
  28.     L.SetDims(r + t, r + t);
  29.     C.SetDims(r, r);
  30.  
  31.     // Construct the lattice L
  32.     for (i = 0; i < r + t; i++)
  33.     {
  34.         for (j = 0; j < r + t; j++)
  35.         {
  36.             L[i][j] = 0;
  37.         }
  38.     }
  39.     for (i = 0; i < t; i++)
  40.         L[i][i] = m;
  41.     for (i = t; i < r + t; i++)
  42.     {
  43.         L[i][i] = power2_ZZ(beta);
  44.         for (j = 0; j < t; j++)
  45.         {
  46.             L[i][j] = y[i + j - t] * power2_ZZ(beta);
  47.         }
  48.     }
  49.  
  50.     // Reduce the lattice L
  51.     BKZ_FP(L, 0.99, 20);
  52.  
  53.     // Choose 3 polynomials that annihilate the sequence a
  54.     for (i = 0; i < r; i++)
  55.     {
  56.         for (j = 0; j < r; j++)
  57.         {
  58.             C[i][j] = L[i][j + t] / power2_ZZ(beta);
  59.         }
  60.     }
  61.  
  62.     auto end = std::chrono::high_resolution_clock::now();
  63.     std::chrono::duration<double> duration = end - start;
  64.     double time_in_seconds = duration.count();
  65.     cout << "Step 1: time of searching polynomials that annihilate the sequence a: " << time_in_seconds << "s\n\n";
  66.  
  67.     return C;
  68. }
  69.  
  70. // Search polynomials that annihilate the sequence a
  71. // The high-order scenario
  72. // The modulus m is unknown
  73. mat_ZZ Search_linear_relations_high(vec_ZZ y, int alpha, int r, int t)
  74. {
  75.     auto start = std::chrono::high_resolution_clock::now();
  76.     mat_ZZ L, C;
  77.     int i, j;
  78.  
  79.     L.SetDims(r + t, r + t);
  80.     C.SetDims(r, r);
  81.  
  82.     // Construct the lattice L
  83.     for (i = 0; i < r + t; i++)
  84.     {
  85.         for (j = 0; j < r + t; j++)
  86.         {
  87.             L[i][j] = 0;
  88.         }
  89.     }
  90.     for (i = 0; i < t; i++)
  91.         L[i][i] = power2_ZZ(alpha);
  92.     for (i = t; i < r + t; i++)
  93.     {
  94.         L[i][i] = 1;
  95.         for (j = 0; j < t; j++)
  96.         {
  97.             L[i][j] = y[i + j - t];
  98.         }
  99.     }
  100.  
  101.     // Reduce the lattice L
  102.     BKZ_FP(L, 0.99, 20);
  103.  
  104.     // Choose 3 polynomials that annihilate the sequence a
  105.     for (i = 0; i < r; i++)
  106.     {
  107.         for (j = 0; j < r; j++)
  108.         {
  109.             C[i][j] = L[i][j + t];
  110.         }
  111.     }
  112.  
  113.     auto end = std::chrono::high_resolution_clock::now();
  114.     std::chrono::duration<double> duration = end - start;
  115.     double time_in_seconds = duration.count();
  116.     cout << "Step 1: time of searching polynomials that annihilate the sequence a: " << time_in_seconds << "s\n\n";
  117.  
  118.     return C;
  119. }
  120.  
  121. // Recover the modulus by the resultant
  122. ZZ Recover_the_modulus(mat_ZZ C, int n, int k, int r)
  123. {
  124.     auto start = std::chrono::high_resolution_clock::now();
  125.     ZZ res, m_power, recovered_m;
  126.     ZZX f, g;
  127.     int i, j, flag;
  128.  
  129.     f.SetLength(r);
  130.     g.SetLength(r);
  131.  
  132.     flag = 0;
  133.     for (i = 0; i < r; i++)
  134.         if (C[0][i] == 0)
  135.             flag = flag + 1;
  136.     if (flag == r)
  137.         cout << "Fail to recover the modulus m!\n";
  138.  
  139.     flag = 2;
  140.     m_power = 0;
  141.     while (flag < r)
  142.     {
  143.         for (i = 0; i < r; i++)
  144.             SetCoeff(f, i, C[flag - 1][i]);
  145.         for (j = 0; j < flag - 1; j++)
  146.         {
  147.             for (i = 0; i < r; i++)
  148.             {
  149.                 SetCoeff(g, i, C[j][i]);
  150.             }
  151.             res = resultant(f, g);
  152.             m_power = GCD(m_power, res);
  153.             //cout << m_power << "\n";
  154.         }
  155.         if (NumBits(m_power) == k * n)
  156.             break;
  157.         flag = flag + 1;
  158.     }
  159.     recovered_m = SqrRoot(SqrRoot(SqrRoot(SqrRoot(m_power))));
  160.  
  161.     auto end = std::chrono::high_resolution_clock::now();
  162.     std::chrono::duration<double> duration = end - start;
  163.     double time_in_seconds = duration.count();
  164.     cout << "Step 2: time of recovering the modulus: " << time_in_seconds << "s\n\n";
  165.     cout << "Number of the annihilating polynomials for recovering the modulus = " << flag << "\n";
  166.  
  167.     return recovered_m;
  168. }
  169.  
  170. // Recover the coefficients by the Chinese Remainder Theorem
  171. ZZ_pX Recover_the_coefficients(mat_ZZ C, ZZ m, int n, int r)
  172. {
  173.     auto start = std::chrono::high_resolution_clock::now();
  174.     ZZ_pX f, g, h;
  175.     mat_ZZ_p C_m;
  176.     ZZ_p c;
  177.     int i, j, mark, flag;
  178.     c.init(m);
  179.  
  180.     C_m.SetDims(r, r);
  181.  
  182.     ofstream fout("C.txt");
  183.     for (i = 0; i < r; i++)
  184.     {
  185.         for (j = 0; j < r; j++)
  186.         {
  187.             fout << C[i][j] << " ";
  188.         }
  189.         fout << "\n";
  190.     }
  191.     fout.close();
  192.     freopen("C.txt", "r", stdin);
  193.  
  194.     // Make the polynomials monic
  195.     for (i = 0; i < r; i++)
  196.     {
  197.         for (j = 0; j < r; j++)
  198.         {
  199.             cin >> c;
  200.             C_m[i][j] = c;
  201.         }
  202.         mark = r - 1;
  203.         while (C_m[i][mark] == 0)
  204.         {
  205.             mark = mark - 1;
  206.         }
  207.         if (mark >= 0)
  208.         {
  209.             for (j = 0; j < r; j++)
  210.             {
  211.                 C_m[i][j] = C_m[i][j] * inv(C_m[i][mark]);
  212.             }
  213.         }
  214.     }
  215.  
  216.     f.SetLength(r);
  217.     g.SetLength(r);
  218.  
  219.     for (i = 0; i < r; i++)
  220.     {
  221.         SetCoeff(f, i, C_m[0][i]);
  222.         SetCoeff(g, i, C_m[1][i]);
  223.     }
  224.  
  225.     h = GCD(f, g);
  226.     flag = 2;
  227.  
  228.     while (deg(h) > n)
  229.     {
  230.         for (i = 0; i < r; i++)
  231.             SetCoeff(f, i, C_m[flag][i]);
  232.         h = GCD(f, h);
  233.         flag = flag + 1;
  234.     }
  235.  
  236.     auto end = std::chrono::high_resolution_clock::now();
  237.     std::chrono::duration<double> duration = end - start;
  238.     double time_in_seconds = duration.count();
  239.     cout << "Step 3: time of recovering the coefficients: " << time_in_seconds << "s\n\n";
  240.     cout << "Number of the annihilating polynomials for recovering the coefficients = " << flag << "\n";
  241.  
  242.     return h;
  243. }
  244.  
  245. // Recover the initial state by Kannan's embedding technique
  246. // The high-order scenario
  247. vec_ZZ Recover_the_initial_state(vec_ZZ y, ZZ_pX f, ZZ m, int n, int d, int beta)
  248. {
  249.     auto start = std::chrono::high_resolution_clock::now();
  250.     vec_ZZ a, z;
  251.     mat_ZZ Q, Q_power, L;
  252.     ZZ b;
  253.     int i, j, l;
  254.  
  255.     a.SetLength(n);
  256.     z.SetLength(n);
  257.     Q.SetDims(n, n);
  258.     Q_power.SetDims(n, n);
  259.     L.SetDims(d + 1, d + 1);
  260.  
  261.     Q_power = ident_mat_ZZ(n);
  262.  
  263.     Q[0][n - 1] = (-rep(f[0])) % m;
  264.     for (i = 1; i < n; i++)
  265.     {
  266.         Q[i][i - 1] = 1;
  267.         Q[i][n - 1] = (-rep(f[i])) % m;
  268.     }
  269.  
  270.     // Construct the lattice L
  271.     for (i = 1; i < n; i++)
  272.     {
  273.         Q_power = Q_power * Q;
  274.         for (j = 0; j < n; j++)
  275.         {
  276.             for (l = 0; l < n; l++)
  277.             {
  278.                 Q_power[j][l] = Q_power[j][l] % m;
  279.             }
  280.         }
  281.     }
  282.  
  283.     for (i = n; i < d; i++)
  284.     {
  285.         Q_power = Q_power * Q;
  286.         for (j = 0; j < n; j++)
  287.         {
  288.             for (l = 0; l < n; l++)
  289.             {
  290.                 Q_power[j][l] = Q_power[j][l] % m;
  291.             }
  292.         }
  293.         b = 0;
  294.         for (j = 0; j < n; j++)
  295.         {
  296.             L[j + 1][i + 1] = Q_power[j][0];
  297.             b += Q_power[j][0] * y[j];
  298.         }
  299.         L[0][i + 1] = (pow(2, beta) * (y[i] - b)) % m + pow(2, beta - 1);
  300.     }
  301.  
  302.     L[0][0] = pow(2, beta - 1);
  303.     for (i = 1; i <= n; i++)
  304.     {
  305.         L[0][i] = pow(2, beta - 1);
  306.         L[i][i] = 1;
  307.     }
  308.     for (i = n + 1; i <= d; i++)
  309.     {
  310.         L[i][i] = m;
  311.     }
  312.  
  313.     // Reduce the lattice L
  314.     BKZ_FP(L, 0.99, 20);
  315.  
  316.     // Recover the initial state
  317.     if (L[0][0] == -pow(2, beta - 1))
  318.     {
  319.         for (i = 0; i < n; i++)
  320.         {
  321.             z[i] = L[0][i + 1] + pow(2, beta - 1);
  322.             a[i] = y[i] * pow(2, beta) + z[i];
  323.         }
  324.     }
  325.     if (L[0][0] == pow(2, beta - 1))
  326.     {
  327.         for (i = 0; i < n; i++)
  328.         {
  329.             z[i] = pow(2, beta - 1) - L[0][i + 1];
  330.             a[i] = y[i] * pow(2, beta) + z[i];
  331.         }
  332.     }
  333.  
  334.     auto end = std::chrono::high_resolution_clock::now();
  335.     std::chrono::duration<double> duration = end - start;
  336.     double time_in_seconds = duration.count();
  337.     cout << "Step 4: time of recovering the initial state: " << time_in_seconds << "s\n\n";
  338.  
  339.     return a;
  340. }
  341.  
  342. void Experiment_2_1(vec_ZZ y, ZZ m, int n, int k)
  343. {
  344.     vec_ZZ recovered_a;
  345.     mat_ZZ C;
  346.     ZZ_pX f;
  347.     int r, t, d, alpha, beta;
  348.     int i;
  349.  
  350.     r = 71;
  351.     t = 71;
  352.     alpha = 17;
  353.     beta = 14;
  354.     d = 30;
  355.  
  356.     C = Search_linear_relations_high_m(m, y, beta, r, t);
  357.     f = Recover_the_coefficients(C, m, n, r);
  358.     cout << "f = " << f << "\n\n\n";
  359.     recovered_a = Recover_the_initial_state(y, f, m, n, d, beta);
  360.     cout << "Number of truncated digits for recovering the initial state = " << d << "\n";
  361.     cout << "a = " << recovered_a << "\n\n\n\n\n";
  362. }
  363.  
  364. void Experiment_3_1(vec_ZZ y, int n, int k)
  365. {
  366.     vec_ZZ recovered_a;
  367.     mat_ZZ C;
  368.     ZZ m;
  369.     ZZ_pX f;
  370.     int r, t, d, alpha, beta;
  371.     int i;
  372.  
  373.     r = 72;
  374.     t = 70;
  375.     alpha = 17;
  376.     beta = 14;
  377.     d = 30;
  378.  
  379.     C = Search_linear_relations_high(y, alpha, r, t);
  380.     m = Recover_the_modulus(C, n, k, r);
  381.     cout << "m = " << m << "\n\n\n";
  382.     f = Recover_the_coefficients(C, m, n, r);
  383.     cout << "f = " << f << "\n\n\n";
  384.     recovered_a = Recover_the_initial_state(y, f, m, n, d, beta);
  385.     cout << "Number of truncated digits for recovering the initial state = " << d << "\n";
  386.     cout << "a = " << recovered_a << "\n\n\n\n\n";
  387. }
  388.  
  389. void main()
  390. {
  391.     vec_ZZ y;
  392.     ZZ m;
  393.     int n, k, i, N;
  394.  
  395.     n = 16;
  396.     k = 31;
  397.     m = 2147483647;
  398.     N = 141;
  399.  
  400.     y.SetLength(N);
  401.     long Y[141] = { 312,6195,20905,36760,33275,128773,5120,82629,3434,13450,115969,78595,46080,21032,126472,116368,39147,118169,53608,16848,30654,130814,92427,66994,64940,95674,83420,12319,51686,121628,103101,4578,55561,114165,99105,66029,11183,33637,126822,45172,71211,75549,31249,100570,57872,40625,53029,98594,35382,114241,86331,100286,74451,71452,113487,22824,119007,42576,9420,18312,62834,3099,103626,124788,28318,119993,120470,1417,66987,121877,100551,36538,107257,95791,90747,11856,78683,27967,33439,112227,42492,76803,73986,127640,127988,113849,62073,121003,67257,62990,28618,14066,37196,88819,91188,119086,47509,14040,46365,117363,96302,61501,69537,19261,5302,29632,112053,60563,73212,123325,7485,52451,92665,108139,31895,6630,28136,97771,1874,10433,123318,98757,45897,34866,118234,75543,95739,41629,82990,25310,28330,21183,102442,39164,13744,125171,78275,42927,27280,113230,115192 };
  402.     for (i = 0; i < N; i++)
  403.         y[i] = ZZ(Y[i]);
  404.  
  405.  
  406.     cout << "***Experiment 2.1***\n";
  407.     Experiment_2_1(y, m, n, k);
  408.  
  409.     cout << "***Experiment 3.1***\n";
  410.     Experiment_3_1(y, n, k);
  411. }
Advertisement
Add Comment
Please, Sign In to add comment