how to use libgcrypt library
Neil Spring
nspring@cs.washington.edu
Sun, 27 Jul 2003 02:40:06 -0700
--Apple-Mail-2--612767107
Content-Transfer-Encoding: 7bit
Content-Type: text/plain; charset=US-ASCII; format=flowed
Zen,
On Tuesday, Jul 22, 2003, at 20:34 US/Pacific, Neil Spring wrote:
> I wrote the following today; you might find it useful, and it seems to
> work.
Sigh. The previous example doesn't work. Although it generated
something I thought was a signature, and did so without errors from
gcrypt, it would verify any string as matching the signature.
gcry_pk_sign and _verify were probably not meant to take a data value
as a quoted string.
The following is an apparently functioning version, with the same
caveats as before -- it may not be the proper series of function calls
to sign a chunk of plaintext, but it seems to work. The main
difference lies in make_sign_parameters().
I also can't seem to use as small a key as I'd like -- anything smaller
than 512 bits causes a GCRYERR_TOO_SHORT. Suggestions for making
smaller signatures with smaller keys would be appreciated --
performance and compactness are much more important to me than
preventing forgeries.
-neil
#include <gcrypt.h>
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
/* either seems to work */
// #define HASH_TYPE GCRY_MD_SHA1
// #define HASH_NAME "sha1"
#define HASH_TYPE GCRY_MD_MD5
#define HASH_NAME "md5"
void make_sign_parameters(GcrySexp *sign_parms, const char *plain) {
size_t errof=0;
int rc;
size_t hash_len = gcry_md_get_algo_dlen(HASH_TYPE);
unsigned char *digest;
GcryMPI mpival;
digest = malloc(hash_len);
gcry_md_hash_buffer(HASH_TYPE, digest, plain, strlen(plain));
gcry_mpi_scan(&mpival, GCRYMPI_FMT_USG, digest, &hash_len);
rc = gcry_sexp_build (sign_parms, &errof,
"(data (flags pkcs1) (hash %s %m))",
HASH_NAME, mpival);
assert(rc == 0);
gcry_mpi_release(mpival);
free(digest);
}
int main (int argc, char **argv) {
static const char message[] = "hello world";
GcrySexp gen_parms, sign_parms, keypair, pubkey, skey, sig, other;
size_t errof=0;
int rc; /* should be gcry_error_t in gcrypt > 1.1.12 */
gcry_control (GCRYCTL_DISABLE_SECMEM, 0);
rc = gcry_sexp_build (&gen_parms, &errof, "(genkey (rsa (nbits
3:512)))");
assert(rc == 0);
rc = gcry_pk_genkey(&keypair, gen_parms);
assert(rc == 0);
skey = gcry_sexp_find_token(keypair, "private-key", 0);
pubkey = gcry_sexp_find_token(keypair, "public-key", 0);
assert(skey != NULL);
assert(pubkey != NULL);
make_sign_parameters(&sign_parms, message);
/* doesn't seem to do what I meant it to:
rc = gcry_sexp_build (&sign_parms, &errof,
"(data (flags raw) (value \"%s\"))\n", message);
*/
rc = gcry_pk_sign (&sig, sign_parms, skey);
if(rc != 0) {
printf("sign returns error %d: %s\n", rc, gcry_strerror(rc));
exit(EXIT_FAILURE);
}
fprintf(stderr, " the s-expression containing the signature is:\n");
gcry_sexp_dump(sig);
make_sign_parameters(&sign_parms, message);
rc = gcry_pk_verify (sig, sign_parms, pubkey);
if(rc != 0) {
printf("verify returns error %d: %s\n", rc, gcry_strerror(rc));
}
/* now make sure it doesn't verify an arbitrary string */
make_sign_parameters(&other, "eat my shorts, man");
rc = gcry_pk_verify (sig, other, pubkey);
if(rc == 0) {
printf("verify verified the wrong thing.\n");
}
exit(EXIT_SUCCESS);
}
--Apple-Mail-2--612767107
content-type: application/pgp-signature; x-mac-type=70674453;
name=PGP.sig
content-disposition: inline
content-transfer-encoding: 7bit
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.2 (Darwin)
iD8DBQE/I538tvhXVvuQ3oQRAvnoAJ9w4ixJqiOmumY6a2tnkdUyR4ZERQCfeO9C
XJ04nBuaLovQpa6x55PWx28=
=1PL9
-----END PGP SIGNATURE-----
--Apple-Mail-2--612767107--