用VHDL生成和验证1024位素数

时间:2015-06-03 22:12:39

标签: rsa vhdl primes largenumber

我正在实施RSA加密,需要生成随机的1024位素数。

由于限制,我无法使用INTEGER信号,因此当我需要执行算术运算时,我使用STD_LOGIC_VECTOR并将其转换为UNSIGNED

  • 我开始使用UNIFORM生成32个随机32位数字,然后将其复制到1024位STD_LOGIC_VECTOR
  • 然后我将最重要和最不重要的位设置为' 1'确保它是1024位和奇数。
  • 然后我使用 Miller Rabin 算法的实现检查素性,这就是我的问题所在。

这是我生成随机素数的地方:

function GEN_1024_PRIME return STD_LOGIC_VECTOR is

  VARIABLE s1, s2 : POSITIVE;
  VARIABLE random : REAL;
  VARIABLE small_random : STD_LOGIC_VECTOR (31 downto 0); 
  VARIABLE large_random : STD_LOGIC_VECTOR (1023 downto 0); 
  VARIABLE prime : STD_LOGIC := '0';

begin

while prime /= '1' loop
  for I in 0 to 31 loop
    UNIFORM(s1, s2, random); 
    small_random := STD_LOGIC_VECTOR(to_unsigned(INTEGER(TRUNC(random * REAL(2147483647))), 32));
    large_random (I*32 + 31 downto I*32) := small_random;
  end loop;

  large_random(0) := '1';
  large_random(1023) := '1';
  prime := MILLER_RABIN (large_random);
end loop;

return large_random;

end function;

我对Miller Rabin的实施:

function MILLER_RABIN (prime : STD_LOGIC_VECTOR (1023 downto 0)) return STD_LOGIC is

  VARIABLE t : INTEGER := 4;
  VARIABLE temp, r, a, x, j, n: UNSIGNED (1023 downto 0); 
  VARIABLE small_random : UNSIGNED (31 downto 0); 
  VARIABLE large_random : UNSIGNED (1023 downto 0); 
  VARIABLE s1, s2 : POSITIVE;
  VARIABLE random : REAL;

begin

n := UNSIGNED(prime);

if n MOD 2 = 0 OR n MOD 3 = 0 then
  return '0';
else
  -- calculate n - 1 = 2^s * r such that r is odd
  r := n - 1;
  while r MOD 2 = 0 loop
    r := r / 2;
  end loop;

  for I in 1 to t loop
    -- choose random a, 2 <= a <= n-2
    for I in 0 to 31 loop
      UNIFORM(s1, s2, random); 
      small_random := to_unsigned(INTEGER(TRUNC(random * REAL(2147483647))), 32);
      large_random (I*32 + 31 downto I*32) := small_random;
    end loop;

    a := large_random;
    temp := r;
    x := MOD_3(a, temp, n); 

    while (temp /= (n - 1) AND x /= 1 AND x /= (n - 1)) loop
      x := (x * x) MOD n;
      temp := temp * 2;
    end loop;

    if x /= (n - 1) AND temp MOD 2 = 0 then
      return '0';
    end if; 

  end loop;

  return '1';
end if;

end function;

function MOD_3 (a, b, c : UNSIGNED (1023 downto 0)) return UNSIGNED is

  VARIABLE x : UNSIGNED (1023 downto 0) := TO_UNSIGNED(1, 1024);
  VARIABLE y : UNSIGNED (1023 downto 0) := a;
  VARIABLE b_temp : UNSIGNED (1023 downto 0) := b;

begin

while b_temp > 0 loop
  if b_temp MOD 2 = 1 then
    x := (x * y) MOD c;
  end if; 
  y := (y * y) MOD c;
  b_temp := b_temp / 2;
end loop;
return x MOD c;

end function;

我将输入转换为UNSIGNED以执行算术运算,看起来它会起作用,直到我意识到将存在2个值的乘积大于1024位的实例。例如,在这个while循环中:

while (temp /= (n - 1) AND x /= 1 AND x /= (n - 1)) loop
  x := (x * x) MOD n;
  temp := temp * 2;
end loop;

temp := temp * 2;的结果是2048位。

我觉得我可以通过搞乱UNSIGNED变量的大小来解决这个问题,但我认为它变得比它需要的更加混乱,所以我想知道我是不是接近这个错误的方式? 是否有更简单的方法来生成1024位素数?是否有另一种素性测试更适合我的问题?

0 个答案:

没有答案