【问题标题】:Error: "invalid use of incomplete type ‘RSA {aka struct rsa_st}" in OpenSSL 1.1.0错误:OpenSSL 1.1.0 中“无效使用不完整类型‘RSA {aka struct rsa_st}”
【发布时间】:2017-05-11 22:10:41
【问题描述】:

我有旧代码是为了链接旧版本的 openssl 而编写的。此代码的一部分从 PEM 文件加载密钥,并尝试使用以下代码了解此密钥是私钥还是公钥:

if( (prv->p==0 || prv->q==0) ) {
    // This is not a private key!
    throw error("No private key for decryption");
}

使用最新版本的 openssl,这(有理由)无法编译:

crypto.cpp: In function ‘key* decrypt_header(file_t, RSA*)’:
crypto.cpp:158:13: error: invalid use of incomplete type ‘RSA {aka struct rsa_st}’
     if( (prv->p==0 || prv->q==0) ) {
             ^~

我知道直接访问结构的私有成员已被一个函数取代,但我很难弄清楚是哪个函数。

【问题讨论】:

    标签: c openssl


    【解决方案1】:

    OpenSSL 1.1.1 之后支持 getter 像这样返回每个参数。

    const BIGNUM *RSA_get0_n(const RSA *d);
    const BIGNUM *RSA_get0_e(const RSA *d);
    const BIGNUM *RSA_get0_d(const RSA *d);
    const BIGNUM *RSA_get0_p(const RSA *d);
    const BIGNUM *RSA_get0_q(const RSA *d);
    const BIGNUM *RSA_get0_dmp1(const RSA *r);
    const BIGNUM *RSA_get0_dmq1(const RSA *r);
    const BIGNUM *RSA_get0_iqmp(const RSA *r);
    

    因此,如果您不需要考虑低于 1.1.1 的 OpenSSL 版本,这些代码将成为简单的代码。和其他结构也支持这种吸气剂。您可以在此处找到有关功能的更多信息。 https://www.openssl.org/docs/man1.1.1/man3/

    【讨论】:

      【解决方案2】:
      #if OPENSSL_VERSION_NUMBER < 0x10100005L
      static void RSA_get0_key(const RSA *r, const BIGNUM **n, const BIGNUM **e, const BIGNUM **d, const BIGNUM **p, const BIGNUM **q)
      {
          if(n != NULL)
              *n = r->n;
      
          if(e != NULL)
              *e = r->e;
      
          if(d != NULL)
              *d = r->d;
      
          if(p != NULL)
              *p = r->p;
      
          if(q != NULL)
              *q = r->q;
      }
      #endif
      
      const BIGNUM *bn_p;
      const BIGNUM *bn_q;
      
      RSA_get0_key(key, NULL, NULL, NULL, &bn_p, &bn_q);
      /*   if( (prv->p==0 || prv->q==0) ) { */
      if( (prv_p==0 || prv_q==0) ) {
      

      【讨论】:

        【解决方案3】:
        crypto.cpp:158:13: error: invalid use of incomplete type ‘RSA {aka struct rsa_st}’
             if( (prv->p==0 || prv->q==0) ) {
                     ^~
        

        如您所知,OpenSSL 1.1.0 改变了许多结构成员的可见性。您不能再直接访问成员。相反,您必须使用 getter 和 setter 函数。

        试试RSA_get0_factorsget0 表示引用计数递增。 不要BN_free他们。

        void RSA_get0_factors(const RSA *r, const BIGNUM **p, const BIGNUM **q);
        

        如果代码支持多个版本的 OpenSSL,那么您将需要一个保护,因为 RSA_get0_factors 用于 OpenSSL 1.1.0 及更高版本。也许像下面这样。另见OPENSSL_VERSION_NUMBER man page

        #include <openssl/opensslv.h>
        
        #if OPENSSL_VERSION_NUMBER < 0x10100000L
        
            /* OpenSSL 1.0.2 and below (old code) */
        
        #else
        
            /* OpenSSL 1.1.0 and above (new code) */
        
        #endif
        

        【讨论】:

        • 谢谢。知道在不重新学习 openssl 的情况下我应该在哪里找到它吗?
        • @ShacharShemesh - 我认为你必须忍受它......1.1.0 Change Log 表示一堆结构被设为私有。因为需要替换,所以我检查了在线 OpenSSL man pages 的 RSA 函数,寻找获取 p 和/或 q 的函数。我从OpenSSL man pages开始,钻到1.1.0,钻到Crypto,然后搜索RSA_。随着时间的推移,OpenSSL wiki 可能会在其示例中积累新代码。
        • get0get1 的事情已经存在了一段时间。当你开始在 Valgrind 下解决问题时,你通常会很早就知道这一点(也是艰难的方式)。您会想知道为什么在调用get1 函数时会发生泄漏,或者您会通过从get0 函数中释放某些内容而导致双重释放的段错误。我指出get0get1 为其他人省去了麻烦。有人会偶然发现这篇文章并有一个“哦该死”的时刻......
        • 我在 2010 年最后一次更新的 FOSS 程序已从 Debian 中删除,因为它不适用于最新版本的 openssl。坦率地说,我正试图让它发挥作用,仅此而已。如果/当我开始更新它时,这将是一个相当大的更新,但不是现在。
        • “这是一个老项目”的哪一部分你不明白? :-) sourceforge.net/projects/rsyncrypto 我已经更新了 Linux 源代码。现在正在努力更新我的 Windows VM,以便我可以创建一个新版本。 2 年没打开了。
        猜你喜欢
        • 2013-01-14
        • 2021-05-24
        • 1970-01-01
        • 2018-06-25
        • 1970-01-01
        • 2019-11-25
        • 2014-01-28
        • 1970-01-01
        相关资源
        最近更新 更多