Advertisement
bling_yu

An Improved Method for Predicting Truncated Multiple Recursive Generators

Mar 13th, 2025 (edited)
161
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 26.26 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 <fstream>
  15. NTL_CLIENT
  16. using namespace std;
  17.  
  18. // Search polynomials that annihilate the sequence a
  19. // The high-order scenario
  20. // The modulus m is known
  21. mat_ZZ Search_linear_relations_high_m(ZZ m, vec_ZZ y, int beta, int r, int t)
  22. {
  23.     clock_t start, end;
  24.     start = clock();
  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.     // Collect annihilating polynomials of 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.     end = clock();
  63.     double time = (double)(end - start) / CLK_TCK;
  64.     cout << "Step 1: time of searching polynomials that annihilate the sequence a: " << time << "s\n\n\n";
  65.  
  66.     return C;
  67. }
  68.  
  69. // Search polynomials that annihilate the sequence a
  70. // The high-order scenario
  71. // The modulus m is unknown
  72. mat_ZZ Search_linear_relations_high(vec_ZZ y, int alpha, int r, int t)
  73. {
  74.     clock_t start, end;
  75.     start = clock();
  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.     // Collect annihilating polynomials of 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.     end = clock();
  114.     double time = (double)(end - start) / CLK_TCK;
  115.     cout << "Step 1: time of searching polynomials that annihilate the sequence a: " << time << "s\n\n\n";
  116.  
  117.     return C;
  118. }
  119.  
  120. // Search polynomials that annihilate the sequence a
  121. // The multi-segment scenario, l = 3
  122. // The modulus m is unknown
  123. mat_ZZ Search_linear_relations_multi_segment_3(vec_ZZ a2, int k2, int r, int t)
  124. {
  125.     clock_t start, end;
  126.     start = clock();
  127.     mat_ZZ L, C;
  128.     int i, j;
  129.  
  130.     L.SetDims(r + t, r + t);
  131.     C.SetDims(r, r);
  132.  
  133.     // Construct the lattice L
  134.     for (i = 0; i < r + t; i++)
  135.     {
  136.         for (j = 0; j < r + t; j++)
  137.         {
  138.             L[i][j] = 0;
  139.         }
  140.     }
  141.     for (i = 0; i < t; i++)
  142.         L[i][i] = power2_ZZ(k2);
  143.     for (i = t; i < r + t; i++)
  144.     {
  145.         L[i][i] = 1;
  146.         for (j = 0; j < t; j++)
  147.         {
  148.             L[i][j] = a2[i + j - t];
  149.         }
  150.     }
  151.  
  152.     // Reduce the lattice L
  153.     BKZ_FP(L, 0.99, 20);
  154.  
  155.     // Collect annihilating polynomials of the sequence a
  156.     for (i = 0; i < r; i++)
  157.     {
  158.         for (j = 0; j < r; j++)
  159.         {
  160.             C[i][j] = L[i][j + t];
  161.         }
  162.     }
  163.  
  164.     end = clock();
  165.     double time = (double)(end - start) / CLK_TCK;
  166.     cout << "Step 1: time of searching polynomials that annihilate the sequence a: " << time << "s\n\n\n";
  167.  
  168.     return C;
  169. }
  170.  
  171. // Search polynomials that annihilate the sequence a
  172. // The multi-segment scenario, l = 5
  173. // The modulus m is unknown
  174. mat_ZZ Search_linear_relations_multi_segment_5(vec_ZZ a2, vec_ZZ a4, int v2, int v4, int v5, int r, int t)
  175. {
  176.     clock_t start, end;
  177.     start = clock();
  178.     mat_ZZ L, C;
  179.     int i, j;
  180.  
  181.     L.SetDims(r + t, r + t);
  182.     C.SetDims(r, r);
  183.  
  184.     // Construct the lattice L
  185.     for (i = 0; i < r + t; i++)
  186.     {
  187.         for (j = 0; j < r + t; j++)
  188.         {
  189.             L[i][j] = 0;
  190.         }
  191.     }
  192.     for (i = 0; i < t; i++)
  193.         L[i][i] = power2_ZZ(v5 - v2);
  194.     for (i = t; i < r + t; i++)
  195.     {
  196.         L[i][i] = power2_ZZ(v4 - v2);
  197.         for (j = 0; j < t; j++)
  198.         {
  199.             L[i][j] = a2[i + j - t] + a4[i + j - t] * power2_ZZ(v4 - v2);
  200.         }
  201.     }
  202.  
  203.     // Reduce the lattice L
  204.     BKZ_FP(L, 0.99, 20);
  205.  
  206.     // Collect annihilating polynomials of the sequence a
  207.     for (i = 0; i < r; i++)
  208.     {
  209.         for (j = 0; j < r; j++)
  210.         {
  211.             C[i][j] = L[i][j + t] / power2_ZZ(v4 - v2);
  212.         }
  213.     }
  214.  
  215.     end = clock();
  216.     double time = (double)(end - start) / CLK_TCK;
  217.     cout << "Step 1: time of searching polynomials that annihilate the sequence a: " << time << "s\n\n\n";
  218.  
  219.     return C;
  220. }
  221.  
  222. // Recover the modulus by the resultant
  223. ZZ Recover_the_modulus(mat_ZZ C, int n, int k, int r)
  224. {
  225.     clock_t start, end;
  226.     start = clock();
  227.     ZZ res, m_power, recovered_m;
  228.     ZZX f, g;
  229.     int i, j, flag;
  230.  
  231.     f.SetLength(r);
  232.     g.SetLength(r);
  233.  
  234.     flag = 0;
  235.     for (i = 0; i < r; i++)
  236.         if (C[0][i] == 0)
  237.             flag = flag + 1;
  238.     if (flag == r)
  239.         cout << "Fail to recover the modulus m!\n";
  240.  
  241.     flag = 2;
  242.     m_power = 0;
  243.     while (flag < r)
  244.     {
  245.         for (i = 0; i < r; i++)
  246.             SetCoeff(f, i, C[flag - 1][i]);
  247.         for (j = 0; j < flag - 1; j++)
  248.         {
  249.             for (i = 0; i < r; i++)
  250.             {
  251.                 SetCoeff(g, i, C[j][i]);
  252.             }
  253.             res = resultant(f, g);
  254.             m_power = GCD(m_power, res);
  255.             //cout << m_power << "\n";
  256.         }
  257.         if (NumBits(m_power) == k * n)
  258.             break;
  259.         flag = flag + 1;
  260.     }
  261.     recovered_m = SqrRoot(SqrRoot(SqrRoot(SqrRoot(m_power))));
  262.  
  263.     end = clock();
  264.     double time = (double)(end - start) / CLK_TCK;
  265.     cout << "Step 2: time of recovering the modulus: " << time << "s\n";
  266.     cout << "Number of the annihilating polynomials for recovering the modulus = " << flag << "\n";
  267.  
  268.     return recovered_m;
  269. }
  270.  
  271. // Recover the coefficients by the Chinese Remainder Theorem
  272. ZZ_pX Recover_the_coefficients(mat_ZZ C, ZZ m, int n, int r)
  273. {
  274.     clock_t start, end;
  275.     start = clock();
  276.     ZZ_pX f, g, h;
  277.     mat_ZZ_p C_m;
  278.     ZZ_p c;
  279.     int i, j, mark, flag;
  280.     c.init(m);
  281.  
  282.     C_m.SetDims(r, r);
  283.  
  284.     ofstream fout("C.txt");
  285.     for (i = 0; i < r; i++)
  286.     {
  287.         for (j = 0; j < r; j++)
  288.         {
  289.             fout << C[i][j] << " ";
  290.         }
  291.         fout << "\n";
  292.     }
  293.     fout.close();
  294.     freopen("C.txt", "r", stdin);
  295.  
  296.     // Make the polynomials monic
  297.     for (i = 0; i < r; i++)
  298.     {
  299.         for (j = 0; j < r; j++)
  300.         {
  301.             cin >> c;
  302.             C_m[i][j] = c;
  303.         }
  304.         mark = r - 1;
  305.         while (C_m[i][mark] == 0)
  306.         {
  307.             mark = mark - 1;
  308.         }
  309.         if (mark >= 0)
  310.         {
  311.             for (j = 0; j < r; j++)
  312.             {
  313.                 C_m[i][j] = C_m[i][j] * inv(C_m[i][mark]);
  314.             }
  315.         }
  316.     }
  317.  
  318.     f.SetLength(r);
  319.     g.SetLength(r);
  320.  
  321.     for (i = 0; i < r; i++)
  322.     {
  323.         SetCoeff(f, i, C_m[0][i]);
  324.         SetCoeff(g, i, C_m[1][i]);
  325.     }
  326.  
  327.     h = GCD(f, g);
  328.     flag = 2;
  329.  
  330.     while (deg(h) > n)
  331.     {
  332.         for (i = 0; i < r; i++)
  333.             SetCoeff(f, i, C_m[flag][i]);
  334.         h = GCD(f, h);
  335.         flag = flag + 1;
  336.     }
  337.     end = clock();
  338.     double time = (double)(end - start) / CLK_TCK;
  339.     cout << "Step 3: time of recovering the coefficients: " << time << "s\n";
  340.     cout << "Number of the annihilating polynomials for recovering the coefficients = " << flag << "\n";
  341.  
  342.     return h;
  343. }
  344.  
  345. // Recover the initial state by Kannan's embedding technique
  346. // The high-order scenario
  347. vec_ZZ Recover_the_initial_state_high(vec_ZZ y, ZZ_pX f, ZZ m, int n, int d, int beta)
  348. {
  349.     clock_t start, end;
  350.     start = clock();
  351.     vec_ZZ a, z;
  352.     mat_ZZ Q, Q_power, L;
  353.     ZZ b;
  354.     int i, j, l;
  355.  
  356.     a.SetLength(n);
  357.     z.SetLength(n);
  358.     Q.SetDims(n, n);
  359.     Q_power.SetDims(n, n);
  360.     L.SetDims(d + 1, d + 1);
  361.  
  362.     Q_power = ident_mat_ZZ(n);
  363.  
  364.     Q[0][n - 1] = (-rep(f[0])) % m;
  365.     for (i = 1; i < n; i++)
  366.     {
  367.         Q[i][i - 1] = 1;
  368.         Q[i][n - 1] = (-rep(f[i])) % m;
  369.     }
  370.  
  371.     // Construct the lattice L
  372.     for (i = 1; i < n; i++)
  373.     {
  374.         Q_power = Q_power * Q;
  375.         for (j = 0; j < n; j++)
  376.         {
  377.             for (l = 0; l < n; l++)
  378.             {
  379.                 Q_power[j][l] = Q_power[j][l] % m;
  380.             }
  381.         }
  382.     }
  383.  
  384.     for (i = n; i < d; i++)
  385.     {
  386.         Q_power = Q_power * Q;
  387.         for (j = 0; j < n; j++)
  388.         {
  389.             for (l = 0; l < n; l++)
  390.             {
  391.                 Q_power[j][l] = Q_power[j][l] % m;
  392.             }
  393.         }
  394.         b = 0;
  395.         for (j = 0; j < n; j++)
  396.         {
  397.             L[j + 1][i + 1] = Q_power[j][0];
  398.             b += Q_power[j][0] * y[j];
  399.         }
  400.         L[0][i + 1] = (pow(2, beta) * (y[i] - b)) % m + pow(2, beta - 1);
  401.     }
  402.  
  403.     L[0][0] = pow(2, beta - 1);
  404.     for (i = 1; i <= n; i++)
  405.     {
  406.         L[0][i] = pow(2, beta - 1);
  407.         L[i][i] = 1;
  408.     }
  409.     for (i = n + 1; i <= d; i++)
  410.     {
  411.         L[i][i] = m;
  412.     }
  413.  
  414.     // Reduce the lattice L
  415.     BKZ_FP(L, 0.99, 20);
  416.  
  417.     // Recover the initial state
  418.     if (L[0][0] == -pow(2, beta - 1))
  419.     {
  420.         for (i = 0; i < n; i++)
  421.         {
  422.             z[i] = L[0][i + 1] + pow(2, beta - 1);
  423.             a[i] = y[i] * pow(2, beta) + z[i];
  424.         }
  425.     }
  426.     if (L[0][0] == pow(2, beta - 1))
  427.     {
  428.         for (i = 0; i < n; i++)
  429.         {
  430.             z[i] = pow(2, beta - 1) - L[0][i + 1];
  431.             a[i] = y[i] * pow(2, beta) + z[i];
  432.         }
  433.     }
  434.  
  435.     end = clock();
  436.     double time = (double)(end - start) / CLK_TCK;
  437.     cout << "Step 4: time of recovering the initial state: " << time << "s\n";
  438.  
  439.     return a;
  440. }
  441.  
  442. // Recover the initial state by Kannan's embedding technique
  443. // The multi-segment scenario, l = 3
  444. vec_ZZ Recover_the_initial_state_multi_segment_3(vec_ZZ a2, ZZ_pX f, ZZ m, int n, int d, int k1, int k2, int k3)
  445. {
  446.     clock_t start, end;
  447.     start = clock();
  448.     vec_ZZ a, a1, a3;
  449.     mat_ZZ Q, Q_power, L;
  450.     ZZ b;
  451.     int i, j, jj;
  452.  
  453.     a.SetLength(n);
  454.     a1.SetLength(n);
  455.     a3.SetLength(n);
  456.     Q.SetDims(n, n);
  457.     Q_power.SetDims(n, n);
  458.     L.SetDims(2 * d + 1, 2 * d + 1);
  459.  
  460.     Q_power = ident_mat_ZZ(n);
  461.  
  462.     Q[0][n - 1] = (-rep(f[0])) % m;
  463.     for (i = 1; i < n; i++)
  464.     {
  465.         Q[i][i - 1] = 1;
  466.         Q[i][n - 1] = (-rep(f[i])) % m;
  467.     }
  468.  
  469.     // Construct the lattice L
  470.     for (i = 1; i < n; i++)
  471.     {
  472.         Q_power = Q_power * Q;
  473.         for (j = 0; j < n; j++)
  474.         {
  475.             for (jj = 0; jj < n; jj++)
  476.             {
  477.                 Q_power[j][jj] = Q_power[j][jj] % m;
  478.             }
  479.         }
  480.     }
  481.  
  482.     for (i = n; i < d; i++)
  483.     {
  484.         Q_power = Q_power * Q;
  485.         for (j = 0; j < n; j++)
  486.         {
  487.             for (jj = 0; jj < n; jj++)
  488.             {
  489.                 Q_power[j][jj] = Q_power[j][jj] % m;
  490.             }
  491.         }
  492.         b = 0;
  493.         for (j = 0; j < n; j++)
  494.         {
  495.             L[j + 1][i + 1] = Q_power[j][0];
  496.             L[j + d + 1][i + 1] = pow(2, k1 + k2) * Q_power[j][0];
  497.             b += Q_power[j][0] * a2[j];
  498.         }
  499.         L[0][i + 1] = (pow(2, k1) * (a2[i] - b)) % m + pow(2, k1 - 1);
  500.     }
  501.  
  502.     L[0][0] = pow(2, k1 - 1);
  503.     for (i = 1; i <= n; i++)
  504.     {
  505.         L[0][i] = pow(2, k1 - 1);
  506.         L[i][i] = 1;
  507.     }
  508.     for (i = n + 1; i <= d; i++)
  509.     {
  510.         L[i][i] = m;
  511.         L[d + i][i] = -pow(2, k1 + k2);
  512.     }
  513.     for (i = d + 1; i <= 2 * d; i++)
  514.         L[0][i] = pow(2, k1 - 1);
  515.  
  516.     if (k1 >= k3)
  517.     {
  518.         for (i = d + 1; i <= 2 * d; i++)
  519.             L[i][i] = pow(2, k1 - k3);
  520.     }
  521.     else
  522.     {
  523.         for (i = 0; i <= 2 * d; i++)
  524.             for (j = 0; j <= 2 * d; j++)
  525.                 L[i][j] = L[i][j] * pow(2, k3 - k1);
  526.         for (i = d + 1; i <= 2 * d; i++)
  527.             L[i][i] = 1;
  528.     }
  529.  
  530.     // Reduce the lattice L
  531.     BKZ_FP(L, 0.99, 20);
  532.  
  533.     // Recover the initial state
  534.     if (k1 >= k3)
  535.     {
  536.         j = 0;
  537.         while (L[j][0] != pow(2, k1 - 1) && L[j][0] != -pow(2, k1 - 1))
  538.             j = j + 1;
  539.         if (L[j][0] == -pow(2, k1 - 1))
  540.         {
  541.             for (i = 0; i < n; i++)
  542.             {
  543.                 a1[i] = L[j][i + 1] + pow(2, k1 - 1);
  544.                 a3[i] = (L[j][i + d + 1] + pow(2, k1 - 1)) / pow(2, k1 - k3);
  545.                 a[i] = (a3[i] * pow(2, k1 + k2) + a2[i] * pow(2, k1) + a1[i]) % m;
  546.             }
  547.         }
  548.         if (L[j][0] == pow(2, k1 - 1))
  549.         {
  550.             for (i = 0; i < n; i++)
  551.             {
  552.                 a1[i] = -L[j][i + 1] + pow(2, k1 - 1);
  553.                 a3[i] = (-L[j][i + d + 1] + pow(2, k1 - 1)) / pow(2, k1 - k3);
  554.                 a[i] = (a3[i] * pow(2, k1 + k2) + a2[i] * pow(2, k1) + a1[i]) % m;
  555.             }
  556.         }
  557.     }
  558.     if (k1 < k3)
  559.     {
  560.         j = 0;
  561.         while (L[j][0] != pow(2, k3 - 1) && L[j][0] != -pow(2, k3 - 1))
  562.             j = j + 1;
  563.         if (L[j][0] == -pow(2, k3 - 1))
  564.         {
  565.             for (i = 0; i < n; i++)
  566.             {
  567.                 a1[i] = (L[j][i + 1] + pow(2, k3 - 1)) / pow(2, k3 - k1);
  568.                 a3[i] = L[j][i + d + 1] + pow(2, k3 - 1);
  569.                 a[i] = (a3[i] * pow(2, k1 + k2) + a2[i] * pow(2, k1) + a1[i]) % m;
  570.             }
  571.         }
  572.         if (L[j][0] == pow(2, k3 - 1))
  573.         {
  574.             for (i = 0; i < n; i++)
  575.             {
  576.                 a1[i] = (-L[j][i + 1] + pow(2, k3 - 1)) / pow(2, k3 - k1);
  577.                 a3[i] = -L[j][i + d + 1] + pow(2, k3 - 1);
  578.                 a[i] = (a3[i] * pow(2, k1 + k2) + a2[i] * pow(2, k1) + a1[i]) % m;
  579.             }
  580.         }
  581.     }
  582.  
  583.     end = clock();
  584.     double time = (double)(end - start) / CLK_TCK;
  585.     cout << "Step 4: time of recovering the initial state: " << time << "s\n";
  586.  
  587.     return a;
  588. }
  589.  
  590. // Recover the initial state by Kannan's embedding technique
  591. // The multi-segment scenario, l = 5
  592. vec_ZZ Recover_the_initial_state_multi_segment_5(vec_ZZ a2, vec_ZZ a4, ZZ_pX f, ZZ m, int n, int d, int k1, int k2, int k3, int k4, int k5)
  593. {
  594.     clock_t start, end;
  595.     start = clock();
  596.     vec_ZZ a, a1, a3, a5;
  597.     mat_ZZ Q, Q_power, L;
  598.     ZZ b;
  599.     int i, j, jj;
  600.  
  601.     a.SetLength(n);
  602.     a1.SetLength(n);
  603.     a3.SetLength(n);
  604.     a5.SetLength(n);
  605.     Q.SetDims(n, n);
  606.     Q_power.SetDims(n, n);
  607.     L.SetDims(3 * d + 1, 3 * d + 1);
  608.  
  609.     Q_power = ident_mat_ZZ(n);
  610.  
  611.     Q[0][n - 1] = (-rep(f[0])) % m;
  612.     for (i = 1; i < n; i++)
  613.     {
  614.         Q[i][i - 1] = 1;
  615.         Q[i][n - 1] = (-rep(f[i])) % m;
  616.     }
  617.  
  618.     // Construct the lattice L
  619.     for (i = 1; i < n; i++)
  620.     {
  621.         Q_power = Q_power * Q;
  622.         for (j = 0; j < n; j++)
  623.         {
  624.             for (jj = 0; jj < n; jj++)
  625.             {
  626.                 Q_power[j][jj] = Q_power[j][jj] % m;
  627.             }
  628.         }
  629.     }
  630.  
  631.     for (i = n; i < d; i++)
  632.     {
  633.         Q_power = Q_power * Q;
  634.         for (j = 0; j < n; j++)
  635.         {
  636.             for (jj = 0; jj < n; jj++)
  637.             {
  638.                 Q_power[j][jj] = Q_power[j][jj] % m;
  639.             }
  640.         }
  641.         b = 0;
  642.         for (j = 0; j < n; j++)
  643.         {
  644.             L[j + 1][i + 1] = Q_power[j][0];
  645.             L[j + d + 1][i + 1] = pow(2, k1 + k2) * Q_power[j][0];
  646.             L[j + d + n + 1][i + 1] = pow(2, k1 + k2 + k3 + k4) * Q_power[j][0];
  647.             b += Q_power[j][0] * (pow(2, k1) * a2[j] + pow(2, k1 + k2 + k3) * a4[j]);
  648.         }
  649.         L[0][i + 1] = (pow(2, k1) * a2[i] + pow(2, k1 + k2 + k3) * a4[i] - b) % m + pow(2, k1 - 1);
  650.     }
  651.  
  652.     L[0][0] = pow(2, k1 - 1);
  653.     for (i = 1; i <= n; i++)
  654.     {
  655.         L[0][i] = pow(2, k1 - 1);
  656.         L[i][i] = 1;
  657.     }
  658.     for (i = n + 1; i <= d; i++)
  659.     {
  660.         L[i][i] = m;
  661.         L[d + n + i][i] = -pow(2, k1 + k2);
  662.         L[2 * d + i][i] = -pow(2, k1 + k2 + k3 + k4);
  663.     }
  664.     for (i = d + 1; i <= 3 * d; i++)
  665.         L[0][i] = pow(2, k1 - 1);
  666.  
  667.     if (k1 >= k3 && k1 >= k5)
  668.     {
  669.         for (i = d + 1; i <= d + n; i++)
  670.             L[i][i] = pow(2, k1 - k3);
  671.         for (i = d + n + 1; i <= d + 2 * n; i++)
  672.             L[i][i] = pow(2, k1 - k5);
  673.         for (i = d + 2 * n + 1; i <= 2 * d + n; i++)
  674.             L[i][i] = pow(2, k1 - k3);
  675.         for (i = 2 * d + n + 1; i <= 3 * d; i++)
  676.             L[i][i] = pow(2, k1 - k5);
  677.     }
  678.     else if (k3 >= k5)
  679.     {
  680.         for (i = 0; i <= 3 * d; i++)
  681.             for (j = 0; j <= 3 * d; j++)
  682.                 L[i][j] = L[i][j] * pow(2, k3 - k1);
  683.         for (i = d + 1; i <= d + n; i++)
  684.             L[i][i] = 1;
  685.         for (i = d + n + 1; i <= d + 2 * n; i++)
  686.             L[i][i] = pow(2, k3 - k5);
  687.         for (i = d + 2 * n + 1; i <= 2 * d + n; i++)
  688.             L[i][i] = 1;
  689.         for (i = 2 * d + n + 1; i <= 3 * d; i++)
  690.             L[i][i] = pow(2, k3 - k5);
  691.     }
  692.     else
  693.     {
  694.         for (i = 0; i <= 3 * d; i++)
  695.             for (j = 0; j <= 3 * d; j++)
  696.                 L[i][j] = L[i][j] * pow(2, k5 - k1);
  697.         for (i = d + 1; i <= d + n; i++)
  698.             L[i][i] = pow(2, k5 - k3);
  699.         for (i = d + n + 1; i <= d + 2 * n; i++)
  700.             L[i][i] = 1;
  701.         for (i = d + 2 * n + 1; i <= 2 * d + n; i++)
  702.             L[i][i] = pow(2, k5 - k3);
  703.         for (i = 2 * d + n + 1; i <= 3 * d; i++)
  704.             L[i][i] = 1;
  705.     }
  706.  
  707.     // Reduce the lattice L
  708.     BKZ_FP(L, 0.99, 20);
  709.  
  710.     // Recover the initial state
  711.     if (k1 >= k3 && k1 >= k5)
  712.     {
  713.         j = 0;
  714.         while (L[j][0] != pow(2, k1 - 1) && L[j][0] != -pow(2, k1 - 1))
  715.             j = j + 1;
  716.         if (L[j][0] == -pow(2, k1 - 1))
  717.         {
  718.             for (i = 0; i < n; i++)
  719.             {
  720.                 a1[i] = L[j][i + 1] + pow(2, k1 - 1);
  721.                 a3[i] = (L[j][i + d + 1] + pow(2, k1 - 1)) / pow(2, k1 - k3);
  722.                 a5[i] = (L[j][i + d + n + 1] + pow(2, k1 - 1)) / pow(2, k1 - k5);
  723.                 a[i] = (a5[i] * pow(2, k1 + k2 + k3 + k4) + a4[i] * pow(2, k1 + k2 + k3) + a3[i] * pow(2, k1 + k2) + a2[i] * pow(2, k1) + a1[i]) % m;
  724.             }
  725.         }
  726.         if (L[j][0] == pow(2, k1 - 1))
  727.         {
  728.             for (i = 0; i < n; i++)
  729.             {
  730.                 a1[i] = -L[j][i + 1] + pow(2, k1 - 1);
  731.                 a3[i] = (-L[j][i + d + 1] + pow(2, k1 - 1)) / pow(2, k1 - k3);
  732.                 a5[i] = (-L[j][i + d + n + 1] + pow(2, k1 - 1)) / pow(2, k1 - k5);
  733.                 a[i] = (a5[i] * pow(2, k1 + k2 + k3 + k4) + a4[i] * pow(2, k1 + k2 + k3) + a3[i] * pow(2, k1 + k2) + a2[i] * pow(2, k1) + a1[i]) % m;
  734.             }
  735.         }
  736.     }
  737.     else if (k3 >= k5)
  738.     {
  739.         j = 0;
  740.         while (L[j][0] != pow(2, k3 - 1) && L[j][0] != -pow(2, k3 - 1))
  741.             j = j + 1;
  742.         if (L[j][0] == -pow(2, k3 - 1))
  743.         {
  744.             for (i = 0; i < n; i++)
  745.             {
  746.                 a1[i] = (L[j][i + 1] + pow(2, k3 - 1)) / pow(2, k3 - k1);
  747.                 a3[i] = L[j][i + d + 1] + pow(2, k3 - 1);
  748.                 a5[i] = (L[j][i + d + n + 1] + pow(2, k3 - 1)) / pow(2, k3 - k5);
  749.                 a[i] = (a5[i] * pow(2, k1 + k2 + k3 + k4) + a4[i] * pow(2, k1 + k2 + k3) + a3[i] * pow(2, k1 + k2) + a2[i] * pow(2, k1) + a1[i]) % m;
  750.             }
  751.         }
  752.         if (L[j][0] == pow(2, k3 - 1))
  753.         {
  754.             for (i = 0; i < n; i++)
  755.             {
  756.                 a1[i] = (-L[j][i + 1] + pow(2, k3 - 1)) / pow(2, k3 - k1);
  757.                 a3[i] = -L[j][i + d + 1] + pow(2, k3 - 1);
  758.                 a5[i] = (-L[j][i + d + n + 1] + pow(2, k3 - 1)) / pow(2, k3 - k5);
  759.                 a[i] = (a5[i] * pow(2, k1 + k2 + k3 + k4) + a4[i] * pow(2, k1 + k2 + k3) + a3[i] * pow(2, k1 + k2) + a2[i] * pow(2, k1) + a1[i]) % m;
  760.             }
  761.         }
  762.     }
  763.     else
  764.     {
  765.         j = 0;
  766.         while (L[j][0] != pow(2, k5 - 1) && L[j][0] != -pow(2, k5 - 1))
  767.             j = j + 1;
  768.         if (L[j][0] == -pow(2, k5 - 1))
  769.         {
  770.             for (i = 0; i < n; i++)
  771.             {
  772.                 a1[i] = (L[j][i + 1] + pow(2, k5 - 1)) / pow(2, k5 - k1);
  773.                 a3[i] = (L[j][i + d + 1] + pow(2, k5 - 1)) / pow(2, k5 - k3);
  774.                 a5[i] = L[j][i + d + n + 1] + pow(2, k5 - 1);
  775.                 a[i] = (a5[i] * pow(2, k1 + k2 + k3 + k4) + a4[i] * pow(2, k1 + k2 + k3) + a3[i] * pow(2, k1 + k2) + a2[i] * pow(2, k1) + a1[i]) % m;
  776.             }
  777.         }
  778.         if (L[j][0] == pow(2, k3 - 1))
  779.         {
  780.             for (i = 0; i < n; i++)
  781.             {
  782.                 a1[i] = (-L[j][i + 1] + pow(2, k5 - 1)) / pow(2, k5 - k1);
  783.                 a3[i] = (-L[j][i + d + 1] + pow(2, k5 - 1)) / pow(2, k5 - k3);
  784.                 a5[i] = -L[j][i + d + n + 1] + pow(2, k5 - 1);
  785.                 a[i] = (a5[i] * pow(2, k1 + k2 + k3 + k4) + a4[i] * pow(2, k1 + k2 + k3) + a3[i] * pow(2, k1 + k2) + a2[i] * pow(2, k1) + a1[i]) % m;
  786.             }
  787.         }
  788.     }
  789.  
  790.     end = clock();
  791.     double time = (double)(end - start) / CLK_TCK;
  792.     cout << "Step 4: time of recovering the initial state: " << time << "s\n";
  793.  
  794.     return a;
  795. }
  796.  
  797. void Experiment_1_1(vec_ZZ a, ZZ m, int n, int k)
  798. {
  799.     vec_ZZ y, recovered_a;
  800.     mat_ZZ C;
  801.     ZZ_pX f;
  802.     int r, t, N, d, alpha, beta;
  803.     int i;
  804.  
  805.     r = 71;
  806.     t = 71;
  807.     N = r + t - 1;
  808.     alpha = 17;
  809.     beta = 14;
  810.     d = 30;
  811.  
  812.     y.SetLength(N);
  813.     for (i = 0; i < N; i++)
  814.     {
  815.         y[i] = a[i] >> beta;
  816.     }
  817.  
  818.     C = Search_linear_relations_high_m(m, y, beta, r, t);
  819.     f = Recover_the_coefficients(C, m, n, r);
  820.     cout << "f = " << f << "\n\n\n";
  821.     recovered_a = Recover_the_initial_state_high(y, f, m, n, d, beta);
  822.     cout << "Number of truncated digits for recovering the initial state = " << d << "\n";
  823.     cout << "a = " << recovered_a << "\n\n\n\n\n";
  824. }
  825.  
  826. void Experiment_2_1(vec_ZZ a, int n, int k)
  827. {
  828.     vec_ZZ y, recovered_a;
  829.     mat_ZZ C;
  830.     ZZ m;
  831.     ZZ_pX f;
  832.     int r, t, N, d, alpha, beta;
  833.     int i;
  834.  
  835.     r = 72;
  836.     t = 70;
  837.     N = r + t - 1;
  838.     alpha = 17;
  839.     beta = 14;
  840.     d = 30;
  841.  
  842.     y.SetLength(N);
  843.     for (i = 0; i < N; i++)
  844.     {
  845.         y[i] = a[i] >> beta;
  846.     }
  847.  
  848.     C = Search_linear_relations_high(y, alpha, r, t);
  849.     m = Recover_the_modulus(C, n, k, r);
  850.     cout << "m = " << m << "\n\n\n";
  851.     f = Recover_the_coefficients(C, m, n, r);
  852.     cout << "f = " << f << "\n\n\n";
  853.     recovered_a = Recover_the_initial_state_high(y, f, m, n, d, beta);
  854.     cout << "Number of truncated digits for recovering the initial state = " << d << "\n";
  855.     cout << "a = " << recovered_a << "\n\n\n\n\n";
  856. }
  857.  
  858. void Experiment_3_1(vec_ZZ a, int n, int k)
  859. {
  860.     vec_ZZ y, recovered_a;
  861.     mat_ZZ A, C;
  862.     ZZ m;
  863.     ZZ_pX f;
  864.     int r, t, N, d, l;
  865.     int i;
  866.  
  867.     // Experiment_3_1
  868.     int K[3] = { 9, 17, 5 };
  869.     int V[3] = { 0, 9, 26 };
  870.     r = 70;
  871.     t = 70;
  872.     N = r + t - 1;
  873.     d = 30;
  874.     l = 3;
  875.  
  876.     // Experiment_3_2
  877.     /*int K[3] = { 12, 14, 5 };
  878.     int V[3] = { 0, 12, 26 };
  879.     r = 105;
  880.     t = 105;
  881.     N = r + t - 1;
  882.     d = 36;
  883.     l = 3;*/
  884.  
  885.     A.SetDims(l, N);
  886.     for (i = 0; i < N; i++)
  887.     {
  888.         A[0][i] = a[i] % power2_ZZ(K[0]);
  889.         A[1][i] = (a[i] >> V[1]) % power2_ZZ(K[1]);
  890.         A[2][i] = a[i] >> V[2];
  891.     }
  892.  
  893.     C = Search_linear_relations_multi_segment_3(A[1], K[1], r, t);
  894.     m = Recover_the_modulus(C, n, k, r);
  895.     cout << "m = " << m << "\n\n\n";
  896.     f = Recover_the_coefficients(C, m, n, r);
  897.     cout << "f = " << f << "\n\n\n";
  898.     recovered_a = Recover_the_initial_state_multi_segment_3(A[1], f, m, n, d, K[0], K[1], K[2]);
  899.     cout << "Number of truncated digits for recovering the initial state = " << d << "\n";
  900.     cout << "a = " << recovered_a << "\n\n\n\n\n";
  901. }
  902.  
  903. void Experiment_3_3(vec_ZZ a, int n, int k)
  904. {
  905.     vec_ZZ y, recovered_a;
  906.     mat_ZZ A, C;
  907.     ZZ m;
  908.     ZZ_pX f;
  909.     int r, t, N, d, l;
  910.     int i;
  911.  
  912.     // Experiment_3_3
  913.     int K[5] = { 6, 3, 3, 14, 5 };
  914.     int V[5] = { 0, 6, 9, 12, 26 };
  915.     r = 104;
  916.     t = 104;
  917.     N = r + t - 1;
  918.     d = 30;
  919.     l = 5;
  920.  
  921.     // Experiment_3_4
  922.     /*int K[5] = { 6, 2, 3, 15, 5 };
  923.     int V[5] = { 0, 6, 8, 11, 26 };
  924.     r = 90;
  925.     t = 90;
  926.     N = r + t - 1;
  927.     d = 31;
  928.     l = 5;*/
  929.  
  930.     A.SetDims(l, N);
  931.     for (i = 0; i < N; i++)
  932.     {
  933.         A[0][i] = a[i] % power2_ZZ(K[0]);
  934.         A[1][i] = (a[i] >> V[1]) % power2_ZZ(K[1]);
  935.         A[2][i] = (a[i] >> V[2]) % power2_ZZ(K[2]);
  936.         A[3][i] = (a[i] >> V[3]) % power2_ZZ(K[3]);
  937.         A[4][i] = a[i] >> V[4];
  938.     }
  939.  
  940.     C = Search_linear_relations_multi_segment_5(A[1], A[3], V[1], V[3], V[4], r, t);
  941.     m = Recover_the_modulus(C, n, k, r);
  942.     cout << "m = " << m << "\n\n\n";
  943.     f = Recover_the_coefficients(C, m, n, r);
  944.     cout << "f = " << f << "\n\n\n";
  945.     recovered_a = Recover_the_initial_state_multi_segment_5(A[1], A[3], f, m, n, d, K[0], K[1], K[2], K[3], K[4]);
  946.     cout << "Number of truncated digits for recovering the initial state = " << d << "\n";
  947.     cout << "a = " << recovered_a << "\n\n\n\n\n";
  948. }
  949.  
  950.  
  951. void main()
  952. {
  953.     vec_ZZ a;
  954.     ZZ m;
  955.     int n, k, i;
  956.  
  957.     n = 16;
  958.     k = 31;
  959.     m = 2147483647;
  960.  
  961.     a.SetLength(300);
  962.     a[0] = 5113033;
  963.     a[1] = 101513454;
  964.     a[2] = 342517303;
  965.     a[3] = 602278014;
  966.     a[4] = 545182365;
  967.     a[5] = 2109832480;
  968.     a[6] = 83899935;
  969.     a[7] = 1353806595;
  970.     a[8] = 56274808;
  971.     a[9] = 220365776;
  972.     a[10] = 1900047307;
  973.     a[11] = 1287703311;
  974.     a[12] = 754976298;
  975.     a[13] = 344592060;
  976.     a[14] = 2072123851;
  977.     a[15] = 1906585150;
  978.     for (i = n; i < 300; i++)
  979.     {
  980.         a[i] = (power2_ZZ(15) * a[i - 1] + power2_ZZ(17) * a[i - 3] + power2_ZZ(21) * a[i - 6] + power2_ZZ(20) * a[i - 12] + 257 * a[i - 16]) % m;
  981.     }
  982.  
  983.     cout << "***Experiment 1.1***\n";
  984.     Experiment_1_1(a, m, n, k);
  985.  
  986.     cout << "***Experiment 2.1***\n";
  987.     Experiment_2_1(a, n, k);
  988.  
  989.     cout << "***Experiment 3.1***\n";
  990.     Experiment_3_1(a, n, k);
  991.  
  992.     cout << "***Experiment 3.3***\n";
  993.     Experiment_3_3(a, n, k);
  994. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement