产生key的接口函数为:
gcry_error_t gcry_pk_genkey (gcry_sexp_t * r_key, gcry_sexp_t parms)
生成的key存放在r_key中,生成key的参数为parms。非对称加密使用S-expressions,典型的参数为:
(genkey (rsa (nbits 4:2048)))
首先需要构造parms,使用下列接口:
gcry_error_t gcry_sexp_new (gcry_sexp_t * r_sexp, const void * buffer , size_t length , int autodetect )
结果存储到r_sexp,buffer是s表达式的字符串表示,length是字符串的长度,如果字符串是null-terminated的,则长度可以为0,autodetect为0,则buffer的格式为canonized format;为1,则自动识别。
生成的key包含public-key和private-key,通过下列结果可以分别提取出来:
gcry_sexp_t gcry_sexp_find_token (const gcry_sexp_t list , const char * token , size_t toklen )
token是token的名字,toklen不是0,则是token的长度,为0表示是null-terminated字符串。
为了存储key,还需要通过下列接口将gcry_sexp_t类型的key转换为字符串或二进制数据:
size_t gcry_sexp_sprint (gcry_sexp_t sexp , int mode , char * buffer , size t maxlength )
mode主要有:
GCRYSEXP_FMT_CANON,二进制数据格式,适合存储到文件。
GCRYSEXP_FMT_ADVANCED,文本格式。
如果buffer为NULL,则返回是存储sexp需要的长度。如果buffer不是NULL,则返回成功存储到buffer的长度,如果buffer太短,则返回0。
产生key的时候,会读取/dev/random,为等待熵的产生,这通常需要等待等久,可以通过(flags transient-key)参数来设置不使用/dev/random,但安全性会降低。
示例函数:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106  | #include <gcrypt.h>enum{    RSA_KEY_LEN_1024 = 1024,    RSA_KEY_LEN_2048 = 2048,    RSA_KEY_lEN_4096 = 4096,};enum{    RSA_KEY_FMT_CANON = GCRYSEXP_FMT_CANON,    RSA_KEY_FMT_ADVANCED = GCRYSEXP_FMT_ADVANCED,};int gcrypt_gen_rsa_key(int key_len, int transient, int format,    unsigned char **public, int *public_len,    unsigned char **private, int *private_len){    gcry_sexp_t key_spec = NULL,                key = NULL,                 pubkey = NULL,                 seckey = NULL ;    char key_exp_str[256];    int ret = 1;    switch (key_len) {    case RSA_KEY_LEN_1024:    case RSA_KEY_LEN_2048:    case RSA_KEY_lEN_4096:        break;    default:        return 1;    };    switch (format) {    case RSA_KEY_FMT_CANON:    case RSA_KEY_FMT_ADVANCED:        break;    default:        return 1;    };    if (sizeof(key_exp_str) ==         snprintf(key_exp_str, sizeof(key_exp_str), "(genkey (rsa %s(nbits 4:%d)))",        transient ? "(flags transient-key) " : "",        key_len))     {        fprintf(stderr, "bufoverflow\n");        return 1;    }    if (gcry_sexp_new(&key_spec, key_exp_str, 0, 1)){        fprintf(stderr, "new S-expression failed\n");        return 1;    }    if (gcry_pk_genkey(&key, key_spec)) {        fprintf(stderr, "genkey failed\n");        goto error;    }    pubkey = gcry_sexp_find_token(key, "public-key", 0);    if (pubkey == NULL) {        fprintf(stderr, "no public-key found\n");        goto error;    }    seckey = gcry_sexp_find_token(key, "private-key", 0);    if (seckey == NULL) {        fprintf(stderr, "no private-key found\n");        goto error;    }         *public_len = gcry_sexp_sprint(pubkey, format, NULL, 0);    *public = malloc(*public_len);    if (*public == NULL) {        fprintf(stderr, "malloc public key failed\n");        goto error;    }    gcry_sexp_sprint(pubkey, format, *public, *public_len);    *private_len = gcry_sexp_sprint(seckey, format, NULL, 0);    *private = malloc(*private_len);    if (*private == NULL) {        fprintf(stderr, "malloc private key failed\n");        goto error;    }    gcry_sexp_sprint(seckey, format, *private, *private_len);    ret = 0;error:    if (key_spec)        gcry_sexp_release(key_spec);    if (key)        gcry_sexp_release(key);    if (pubkey)        gcry_sexp_release(pubkey);    if (seckey)        gcry_sexp_release(seckey);    return ret;} | 
参考:
https://stackoverflow.com/questions/39335323/gcry-pk-genkey-function-is-extremely-slow-in-libgcrypt