1

I'm trying to extract the encrypted RSA data from a gcry_sexp_t object (which I assume is an MPI), so I could store the encrypted data as an encrypted file (without the other gcrypt metadata in the sexp object).

I've tried using gcry_sexp_sprint, which serialized the whole sexp object and which kind of works, but I assume that is not the intended way for storing RSA encrypted bytes on the disk. I've also tried extracting data using gcry_sexp_nth_buffer and gcry_sexp_nth_mpi, both of which just return the string enc-val.

This code is the relevant part:

    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)));
    }

After this, I have a gcry_sexp_t object holding all of the relevant data, of which I would like to extract the encrypted data.

Thank you!

EDIT: I ended up calling gcry_sexp_nth two times to traverse the nested S expression object and then using gcry_sexp_nth_data to get the raw encrypted data. I'm sure there's a better way, though.

1 Answers1

2

Libgcrypt API to deal with SExpression is very powerful. You can get data from the expression easily. Here is a sample code which:

  1. Generate key pair

  2. Encrypt a random data

  3. Extract cipher text value

     #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;
     }
    

And this is the output:

    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
Mostafa Barmshory
  • 1,849
  • 24
  • 39