1

我正在尝试从一个gcry_sexp_t对象(我假设它是一个 MPI)中提取加密的 RSA 数据,因此我可以将加密的数据存储为加密文件(在 sexp 对象中没有其他 gcrypt 元数据)。

我尝试过使用gcry_sexp_sprint,它序列化了整个 sexp 对象以及哪种工作方式,但我认为这不是在磁盘上存储 RSA 加密字节的预期方式。我还尝试使用gcry_sexp_nth_bufferand提取数据gcry_sexp_nth_mpi,两者都只返回字符串enc-val

此代码是相关部分:

    gcry_sexp_t ciph;
    err = gcry_pk_encrypt(&ciph, msgSexp, this->publicKey);

    if(err){
        throw std::runtime_error("gcry_pk_encrypt error:  " + std::string(gcry_strerror(err)));
    }

在此之后,我有一个包含gcry_sexp_t所有相关数据的对象,我想从中提取加密数据。

谢谢!

编辑:我最终调用gcry_sexp_nth了两次来遍历嵌套的 S 表达式对象,然后使用gcry_sexp_nth_data来获取原始加密数据。不过,我确信有更好的方法。

4

1 回答 1

2

处理 SExpression 的 Libgcrypt API 非常强大。您可以轻松地从表达式中获取数据。这是一个示例代码:

  1. 生成密钥对

  2. 加密随机数据

  3. 提取密文值

     #include <stdio.h>
     #include <gcrypt.h>
     #include <string.h>
    
     static void die(const char *format, ...) {
         va_list arg_ptr;
         va_start(arg_ptr, format);
         vfprintf(stderr, format, arg_ptr);
         va_end(arg_ptr);
         if (*format && format[strlen(format) - 1] != '\n') {
             putc('\n', stderr);
         }
         exit(1);
     }
    
     static void show_sexp(const char *prefix, gcry_sexp_t a) {
         char *buf;
         size_t size;
    
         if (prefix)
             fputs(prefix, stderr);
         size = gcry_sexp_sprint(a, GCRYSEXP_FMT_ADVANCED, NULL, 0);
         buf = gcry_xmalloc(size);
    
         gcry_sexp_sprint(a, GCRYSEXP_FMT_ADVANCED, buf, size);
         fprintf(stderr, "%.*s", (int) size, buf);
         gcry_free(buf);
     }
    
     int main() {
         gcry_sexp_t key_spec, key, pub_key, sec_key;
         int rc;
         size_t len;
         gcry_sexp_t cipher, l;
         gcry_sexp_t plain;
         gcry_mpi_t x;
         const int nbits_data = 512;
    
         //-------------------------------------------------------------------
         // Generate Key
         //-------------------------------------------------------------------
         rc = gcry_sexp_new(&key_spec, "(genkey (rsa (nbits 4:2048)))", 0, 1);
         if (rc) {
             die("error creating S-expression: %s\n", gcry_strerror(rc));
         }
         //>> Generate key
         rc = gcry_pk_genkey(&key, key_spec);
         gcry_sexp_release(key_spec);
         if (rc) {
             die("error generating RSA key: %s\n", gcry_strerror(rc));
         }
         show_sexp("generated RSA key:\n", key);
    
         //>> Extract parts
         pub_key = gcry_sexp_find_token(key, "public-key", 0);
         if (!pub_key) {
             die("public part missing in key\n");
         }
    
         sec_key = gcry_sexp_find_token(key, "private-key", 0);
         if (!sec_key) {
             die("private part missing in key\n");
         }
    
         //-------------------------------------------------------------------
         // Encrypt Data
         //-------------------------------------------------------------------
         //>> Create plain text.
         x = gcry_mpi_new(nbits_data);
         gcry_mpi_randomize(x, nbits_data, GCRY_WEAK_RANDOM);
         rc = gcry_sexp_build(&plain, NULL, "(data (flags raw) (value %m))", x);
         if (rc) {
             die("converting data for encryption failed: %s\n", gcry_strerror(rc));
         }
    
         //>> Encrypt data.
         rc = gcry_pk_encrypt(&cipher, plain, pub_key);
         if (rc) {
             die("encryption failed: %s\n", gcry_strerror(rc));
         }
    
         //-------------------------------------------------------------------
         // Extract value
         //-------------------------------------------------------------------
         show_sexp("Encrypted data:\n", cipher);
         l = gcry_sexp_find_token(cipher, "a", 0);
    
         const char *data = gcry_sexp_nth_data(l, 1, &len);
         for (int i = 0; i < len; i++) {
             printf("%02x", (unsigned char) data[i]);
         }
         printf("\n");
    
         return 0;
     }
    

这是输出:

    generated RSA key:
    (key-data 
     (public-key 
      (rsa 
       (n #00D43DB15B8AB929675C0196F8750451F2814F62FBF36219008051F99C82EB89B138FAFCBA51DB24D1DAADF6706016C268F59C793E91F05630376E58DCFAE728EEA1D26714244334643BB3A285D0860E9800ECBD5B85B11F4962F438A6C6D465851A991426A4AFF819D1B0D2DA28C016B80613B28070EAEC54A8CDF8EB5D04F03E8F925E384B75D3CEF326CF03901AD053925DFA08B0E8A38E8F6D1C4E14299312FB38791D23EDDFB9B57CAD596BFF09C4EEE0AF85CFC5A228BA5330A8C6F17B233FF8EB351B35C2FD26C3C723B9E4E89A3728D33D5D6C4D35931A0463FBF3FA1D056B4A5B1274BBB82B345130C2DE0FBCC4C258ED2EE3AA28A149A20A6BA0B2C7#)
       (e #010001#)
       )
      )
     (private-key 
      (rsa 
       (n #00D43DB15B8AB929675C0196F8750451F2814F62FBF36219008051F99C82EB89B138FAFCBA51DB24D1DAADF6706016C268F59C793E91F05630376E58DCFAE728EEA1D26714244334643BB3A285D0860E9800ECBD5B85B11F4962F438A6C6D465851A991426A4AFF819D1B0D2DA28C016B80613B28070EAEC54A8CDF8EB5D04F03E8F925E384B75D3CEF326CF03901AD053925DFA08B0E8A38E8F6D1C4E14299312FB38791D23EDDFB9B57CAD596BFF09C4EEE0AF85CFC5A228BA5330A8C6F17B233FF8EB351B35C2FD26C3C723B9E4E89A3728D33D5D6C4D35931A0463FBF3FA1D056B4A5B1274BBB82B345130C2DE0FBCC4C258ED2EE3AA28A149A20A6BA0B2C7#)
       (e #010001#)
       (d #29943875AD949EB6E00073BA12FA98AF4083F3E95601E6D201518DEC0A7DE848AED804C0DF9E65F532B917E965F9AF766E7F8C052504076E84BD7A6D383E26F7B0FE0E3194F511837D6AB0B1346BBEDA2A7C3690827D739AA5E7205E13DFB24FC4292F186EF5064ED094AA8A10A7A90BBE2D07B03FEED603B3DA3E24A5E17CCAF93E8CF54DE7C690FA08C4D57691FB47F637C283B6B8F2752F1FDDF303E5DA3D32ECCE9EE36F78AE83C74C0F875A11E3F907F7DA2197138BC22709123FAC72FD65937E730B99372BDC5A94958A288B67D448534CBB11CCEDA4D5DDB83040FA373932520A0268EE3CCD9BCD3D1040E7DD177E452DBD0CA91442AA39E29A2614F9#)
       (p #00DA039BF562531FA1E2098E0D642D38DB35FCE5CC7D56EE397A2BBAE61DE0777341024D914183C6B9EF83FAE962BC4EC4DA3036B643FD1F6E8EF20E489AF9FA997F860F80DA672B85216DAAEFA91059ED340EB8A7411A2DCDCCE23DB0AB414B8BD2FFB516E23B8AB0D95717DE5A253EC96A7B2FD1BFDA3B001CA590200FEF1F6B#)
       (q #00F93893CE49EB488250AA6D1F568CA14D247EBBEA2FC47D70A5BBF211543DF06F3B5BA51F4119481371B6433D6C1150F14EB19C5C44B7335F4FF3BE3C2FBDC8E17920CEC5D194A71E9F6B0715D7CD6867AB6D0F384A02CDECBBE111BB1276DAD40B872268E3381F3032C44D8B01BC80ACDC3C19D04735D1007202085E345C1D15#)
       (u #00AFC622BC85AB68634EE4EBE0AAFA9DD612A11E7E09657AC937FFD4642622BD63BF825ACD419F273D86E77D74AAA6FBB8A28C633D58C6DDE1F9C5655B5AF8E412CDDA43DCA008EE084AB45D9C8DB454601D7CBB4739692FA91FD910A8A67D5041E339FBD2920875439F5D97C574E21A9DE8C779ADDF67686A940221E4518B6AE4#)
       )
      )
     )
    Encrypted data:
    (enc-val 
     (rsa 
      (a #4CAC81402948B4E0A0FEFCECF89C389D711AAD158D3B6A927FA7D6D276C6BD7AAACA2CDEBB88A2430A0948AD9CFB2192D6521B90C291EDC122D6E7422915FCB083C987204CADCC6BF956B296C33A1CADBF5972921FE58454A6076E29B368195739FDAD3D02D612147E413E7E01E6185CA1784DA2F31874DE9C3DFB31DEE4764BA066BF208C0F362EB25C780001D5AD285DBD41450C735AFBFEE8CF35A178A007865629DC5A3ED50257E473DF73DC02422924E1541393824B91336D30F3989CA2FE8E4BA463673F1BF83EC0D95E958FD2B757699F805B342D52729232568228E01632607821CC9F116580496C228524FD4E3147CF6F6E9456FBBAD1FFD1889F0D#)
      )
     )
    4cac81402948b4e0a0fefcecf89c389d711aad158d3b6a927fa7d6d276c6bd7aaaca2cdebb88a2430a0948ad9cfb2192d6521b90c291edc122d6e7422915fcb083c987204cadcc6bf956b296c33a1cadbf5972921fe58454a6076e29b368195739fdad3d02d612147e413e7e01e6185ca1784da2f31874de9c3dfb31dee4764ba066bf208c0f362eb25c780001d5ad285dbd41450c735afbfee8cf35a178a007865629dc5a3ed50257e473df73dc02422924e1541393824b91336d30f3989ca2fe8e4ba463673f1bf83ec0d95e958fd2b757699f805b342d52729232568228e01632607821cc9f116580496c228524fd4e3147cf6f6e9456fbbad1ffd1889f0d
于 2020-06-24T01:03:17.020 回答