破解RSA中一些特殊的公開模數N


破解RSA中一些特殊的公開模數N

實驗內容:

在公開的N沒有被正確的生成時破解RSA。通常在RSA中構成模數N的素數q和p,應該獨立生成。如果開發者使用一個隨機數R,並選擇R附近的兩個素數作為q和p,那么這種情況情況下生成的RSA模數N就很容易被破解。

任務1

假設給定合數N和兩個彼此很接近的素數q和p,q和p滿足以下關系:

令A為q和p的算數平均值,由於p和q都是奇數,所以A一定為整數。觀察式子(*)可得
,那么A 可能會非常接近,那么任務1中就有以下信息存在:

q,p,A,的關系如下圖:

由於A為整數,我們可以去A = ceil(sqrt(N)),其中ceil()是向上取整的函數。在GMP中mpz_sqrt()默認是向下取整的,那么。
由於p和q在A的附近,我們可以取整數x,滿足以下條件。

那么我們可以反推,那么我們根據x和A就可以得到q和p了。

任務1代碼實現

  void solve_question_one(const mpz_class& N, mpz_class& q, mpz_class& p){
    //計算ceil(sqrt(N))
    mpz_class A;
    mpz_sqrt(A.get_mpz_t(),N.get_mpz_t());//sqrt向下取整
    A++;

    // N  = A^2 - X^2 = (A - x)(A + X)  ->  x = sqrt(A^2 - N)
    mpz_class AA,x;
    AA = A*A - N;
    mpz_sqrt(x.get_mpz_t(),AA.get_mpz_t());
    q = A - x;
    p = A + x;
}

這里的mpz_sqrt()函數是向下取整的,所以只需要在上加1,就行了。mpz_class 是對mpz_t 的封裝,比用c類型mpz_t要好一點,mpz_t類型首先要調用init,其次再使用完畢后還需要調用clear()函數。還有就是mpz_class 轉mpz_t可以使用get_mpz_t()函數,也可以使用(mpz_t)map_class對象,進行類型轉換。這里給出mpz_class 的類的定義:

/**************** mpq_class -- wrapper for mpq_t ****************/

template <>
class __gmp_expr<mpq_t, mpq_t>
{
private:
  typedef mpq_t value_type;
  value_type mp;
  // Helper functions used for all arithmetic types
  void assign_ui(unsigned long l) { mpq_set_ui(mp, l, 1); }
  void assign_si(signed long l)
  {
    if (__GMPXX_CONSTANT_TRUE(l >= 0))
      assign_ui(l);
    else
      mpq_set_si(mp, l, 1);
  }
  void assign_d (double d)        { mpq_set_d (mp, d); }
  void init_ui(unsigned long l) { mpq_init(mp); get_num() = l; }
  void init_si(signed long l) { mpq_init(mp); get_num() = l; }
  void init_d (double d)  { mpq_init(mp); assign_d (d); }
public:
  mp_bitcnt_t get_prec() const { return mpf_get_default_prec(); }
  void canonicalize() { mpq_canonicalize(mp); }
  // constructors and destructor
  __gmp_expr() { mpq_init(mp); }
  __gmp_expr(const __gmp_expr &q)
  {
    mpz_init_set(mpq_numref(mp), mpq_numref(q.mp));
    mpz_init_set(mpq_denref(mp), mpq_denref(q.mp));
  }
#if __GMPXX_USE_CXX11
  __gmp_expr(__gmp_expr &&q)
  { *mp = *q.mp; mpq_init(q.mp); }
#endif
  template <class T>
  __gmp_expr(const __gmp_expr<mpz_t, T> &expr)
  { mpq_init(mp); __gmp_set_expr(mp, expr); }
  template <class T>
  __gmp_expr(const __gmp_expr<mpq_t, T> &expr)
  { mpq_init(mp); __gmp_set_expr(mp, expr); }
  template <class T, class U>
  explicit __gmp_expr(const __gmp_expr<T, U> &expr)
  { mpq_init(mp); __gmp_set_expr(mp, expr); }
  __GMPXX_DEFINE_ARITHMETIC_CONSTRUCTORS
  explicit __gmp_expr(const char *s, int base = 0)
  {
    mpq_init (mp);
    // If s is the literal 0, we meant to call another constructor.
    // If s just happens to evaluate to 0, we would crash, so whatever.
    if (s == 0)
      {
  // Don't turn mpq_class(0,0) into 0
  mpz_set_si(mpq_denref(mp), base);
      }
    else if (mpq_set_str(mp, s, base) != 0)
      {
        mpq_clear (mp);
        throw std::invalid_argument ("mpq_set_str");
      }
  }
  explicit __gmp_expr(const std::string &s, int base = 0)
  {
    mpq_init(mp);
    if (mpq_set_str (mp, s.c_str(), base) != 0)
      {
        mpq_clear (mp);
        throw std::invalid_argument ("mpq_set_str");
      }
  }
  explicit __gmp_expr(mpq_srcptr q)
  {
    mpz_init_set(mpq_numref(mp), mpq_numref(q));
    mpz_init_set(mpq_denref(mp), mpq_denref(q));
  }
  __gmp_expr(const mpz_class &num, const mpz_class &den)
  {
    mpz_init_set(mpq_numref(mp), num.get_mpz_t());
    mpz_init_set(mpq_denref(mp), den.get_mpz_t());
  }
  ~__gmp_expr() { mpq_clear(mp); }
  void swap(__gmp_expr& q) __GMPXX_NOEXCEPT { std::swap(*mp, *q.mp); }
  // assignment operators
  __gmp_expr & operator=(const __gmp_expr &q)
  { mpq_set(mp, q.mp); return *this; }
#if __GMPXX_USE_CXX11
  __gmp_expr & operator=(__gmp_expr &&q) noexcept
  { swap(q); return *this; }
  __gmp_expr & operator=(mpz_class &&z) noexcept
  { get_num() = std::move(z); get_den() = 1u; return *this; }
#endif
  template <class T, class U>
  __gmp_expr<value_type, value_type> & operator=(const __gmp_expr<T, U> &expr)
  { __gmp_set_expr(mp, expr); return *this; }
  __GMPXX_DEFINE_ARITHMETIC_ASSIGNMENTS
  __gmp_expr & operator=(const char *s)
  {
    if (mpq_set_str (mp, s, 0) != 0)
      throw std::invalid_argument ("mpq_set_str");
    return *this;
  }
  __gmp_expr & operator=(const std::string &s)
  {
    if (mpq_set_str(mp, s.c_str(), 0) != 0)
      throw std::invalid_argument ("mpq_set_str");
    return *this;
  }
  // string input/output functions
  int set_str(const char *s, int base)
  { return mpq_set_str(mp, s, base); }
  int set_str(const std::string &s, int base)
  { return mpq_set_str(mp, s.c_str(), base); }
  std::string get_str(int base = 10) const
  {
    __gmp_alloc_cstring temp(mpq_get_str(0, base, mp));
    return std::string(temp.str);
  }
  // conversion functions
  // casting a reference to an mpz_t to mpz_class & is a dirty hack,
  // but works because the internal representation of mpz_class is
  // exactly an mpz_t
  const mpz_class & get_num() const
  { return reinterpret_cast<const mpz_class &>(*mpq_numref(mp)); }
  mpz_class & get_num()
  { return reinterpret_cast<mpz_class &>(*mpq_numref(mp)); }
  const mpz_class & get_den() const
  { return reinterpret_cast<const mpz_class &>(*mpq_denref(mp)); }
  mpz_class & get_den()
  { return reinterpret_cast<mpz_class &>(*mpq_denref(mp)); }
  mpq_srcptr __get_mp() const { return mp; }
  mpq_ptr __get_mp() { return mp; }
  mpq_srcptr get_mpq_t() const { return mp; }
  mpq_ptr get_mpq_t() { return mp; }
  mpz_srcptr get_num_mpz_t() const { return mpq_numref(mp); }
  mpz_ptr get_num_mpz_t() { return mpq_numref(mp); }
  mpz_srcptr get_den_mpz_t() const { return mpq_denref(mp); }
  mpz_ptr get_den_mpz_t() { return mpq_denref(mp); }
  double get_d() const { return mpq_get_d(mp); }
#if __GMPXX_USE_CXX11
  explicit operator bool() const { return mpq_numref(mp)->_mp_size != 0; }
#endif
  // compound assignments
  __GMP_DECLARE_COMPOUND_OPERATOR(operator+=)
  __GMP_DECLARE_COMPOUND_OPERATOR(operator-=)
  __GMP_DECLARE_COMPOUND_OPERATOR(operator*=)
  __GMP_DECLARE_COMPOUND_OPERATOR(operator/=)
  __GMP_DECLARE_COMPOUND_OPERATOR_UI(operator<<=)
  __GMP_DECLARE_COMPOUND_OPERATOR_UI(operator>>=)
  __GMP_DECLARE_INCREMENT_OPERATOR(operator++)
  __GMP_DECLARE_INCREMENT_OPERATOR(operator--)
};

任務2

模數N是q和p的乘積,滿足條件,在的情況下可以從向上搜索,求解q和p。

任務2代碼實現

void solve_question_two(const mpz_class& N,mpz_class& q, mpz_class& p)
{
    //模數N 是兩個素數q,p 的乘積,滿足|p-q| < 2^11 *N^{1/4}

    mpz_class A;
    mpz_sqrt(A.get_mpz_t(),N.get_mpz_t());//sqrt向下取整
    // 從sqrt(N) 向上尋找A 
    int i_max = pow(2,19);
    mpz_class x;
    for(int i = 1 ; i < i_max;i++ ){
        A ++;
        mpz_class temp = A*A - N;
        mpz_sqrt(x.get_mpz_t(),temp.get_mpz_t());
        q = A - x;p = A + x;
        if(q*p == N){
            cout<<"此時A = "<<A<<endl;
            break;
        }
    }
}

代碼的意思就相隔很近,從向上暴力破解,直到搜索到滿足條件,就終止循環。

實驗結果

代碼地址

https://github.com/cyssmile/cplus/blob/master/密碼學實驗部分/solve_RSA_N.cpp

編譯命令自己修改

 D:\cygwin64\bin\g++.exe d:\win_worksapce\solve_RSA_N.cpp -o d:\win_worksapce\main.exe  -lgmpxx -lgmp 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM