|
View:
New views
1 Messages
—
Rating Filter:
Alert me
|
|
|
Signing and Verifying of a public key with a DSA master keyDear OpenSSL Gurus,
For my master thesis, im struggling about three weeks now with the openssl signing and verifying. I even compiled the library in debug mode to understand how it works. I'm using OpenSSL 0.9.7 on Fedora 7 i686 I generated a pair of master DSA keys on the command line as follows: $ openssl dsaparam -out master.params -genkey 128 Generating DSA parameters, 128 bit long prime This could take some time ...............+...........+++++++++++++++++++++++++++++++++++++++++++++++++++* ....+.+...............+......................+...+++++++++++++++++++++++++++++++++++++++++++++++++++* $ openssl gendsa -out master_priv.pem -des3 master.params Generating DSA key, 512 bits Enter PEM pass phrase: Verifying - Enter PEM pass phrase: $ openssl dsa -in master.params -out master_pub.pem -pubout read DSA key writing DSA key The passphrase for this example is simply "secret". I read the master keys with PEM_read_DSAPrivateKey() and PEM_read_DSA_PUBKEY() in the two DSA structures: DSA *master_priv_key, *master_pub_key; Here my master_private.pem: -----BEGIN DSA PRIVATE KEY----- Proc-Type: 4,ENCRYPTED DEK-Info: DES-EDE3-CBC,53888FF0ECB4D8C6 sTS3cY82L+1y2duj6Sq9seKzPTJmfc84uzaYkC90/H8GQaniHjDcs4RlO2wDk2mt TVYBNKOOQd1XoTKrZ4ureyOX5i7Jw9XintSm2Wgj8Hd0VuN05LuA3JxHsXOf89bK NC3QlskUQJf6a4U1MTlB4Bg8rVjve9AfN+jcwnjSKB/vy3xeddv1oyikcKgtl63x DuFnDdPtNEprHKD/adDlgh5EoiUc5gAiyWSGlH3Loj0XWTtTe7kmWfs8JNqavyaQ dVeXj9AWPJ2/2f3t4EPHYHZwUXzc/wcjpJmEnS9qH9lJvWICIeM4ByS8LudPjAw1 +WpA6/pjljQuNr6eKtG6bg== -----END DSA PRIVATE KEY----- and here my master_pub.pem: -----BEGIN PUBLIC KEY----- MIHwMIGoBgcqhkjOOAQBMIGcAkEAzsZuyZ3CDqMCDR+cKkcEzhrVMU+8xGfX2wnd pxD0kZ2AMvzGLXllAqTTvRnjC+u4dAcTsnRXDkQLIZ/ZH0lIDQIVAIaxw2UXhOke 578H1v35K7CkkDB5AkBD14zYMMsWrcRZSK8Whoj5dtZDhikN2zhzCzdfSG9odDa9 rZVSlRb4FkVRdFMR7gnpKb2DreKt8U13OH5f36jOA0MAAkAsIOOQi9VzY1Gtt16P C2v9Z2w8mDwYCGYgCk0i4B6e2sVfTeArIOhx0bp/IaQ7Wu2/WreVGWN5nV2mHHb1 GZ+b -----END PUBLIC KEY----- My KEY structure to manage the keys loos like: typedef struct key { char email[EMAIL_BUF_LEN]; DSA *dsa; /* public key of the user */ unsigned char sig_buf[EVP_MAX_MD_SIZE]; /* buffer for the signature of the public key */ unsigned int sig_len; /* length of the serialised signature in net format */ time_t last_use; int flags; hostid_t *pend; int num_req; struct key *prev; struct key *next; } KEY; The two functions for signing and verifying look as follows, but there is a log of logging information to understand how it works. int pers_signKey(KEY *pubkey) { EVP_MD_CTX mdctx; /* context for the message digest containing the hash value of the public key to sign */ EVP_PKEY *pkey; /* envelope key opject containing the DSA key */ unsigned char key_buf[DSA_BUF_LEN]; /* buffer to put the serialised public key */ unsigned int buf_len; /* variable to store the key length */ unsigned char *ptr; /* a pointer to move over the buffers in the openssl framework */ if (!((master_priv_key) && (is_regauth))) { log(LOG_ERR, "pers_signKey --> no private key to sign or not a registration authority.\n"); return DSA_ERROR; } /* get rid of old signatures */ if (pubkey->sig_len) pubkey->sig_len = 0; memset(pubkey->sig_buf, 0, EVP_MAX_MD_SIZE); /* serialise the public key to sign in key_buf The pointer on this buffer must be a local variable because it will be incremented during the procedure pointing to the address behind key_buf + buf_len */ /* NOTE i2d_DSAPublicKey seems somehow to free the memory of key_buf but it is used again to update the messigae digest context anyway it is not longer possible to free it after this call */ ptr = key_buf; if ((buf_len = i2d_DSAPublicKey(pubkey->dsa, &ptr)) < 0) { init_logSslErrors("pers_signKey"); return DSA_ERROR; } if (buf_len > DSA_BUF_LEN) { log(LOG_ERR, "pers_signKey --> serialised key exeeds DSA_BUF_LEN %d / %d.\n", buf_len, DSA_BUF_LEN); return DSA_ERROR; } /* initialise the context for hashing with the SHA1 algorithm */ if (!(EVP_SignInit(&mdctx, EVP_dss1()))) { init_logSslErrors("pers_signKey (EVP_DigestInit)"); return DSA_ERROR; } /* update the context with the serialised key to hash */ if (!(EVP_SignUpdate(&mdctx, key_buf, buf_len))) { init_logSslErrors("pers_signKey (EVP_DigestUpdate)"); return DSA_ERROR; } /* create the envelope key */ if (!(pkey = EVP_PKEY_new())) { init_logSslErrors("pers_signKey (EVP_PKEY_new)"); return DSA_ERROR; } /* put the private master key into the envelope, don't use EVP_PKEY_assign_DSA or you loose the DSA key too on freeing the EVP_PKEY */ if (!(EVP_PKEY_set1_DSA(pkey, master_priv_key))) { init_logSslErrors("pers_signKey (EVP_PKEY_set1_DSA)"); EVP_PKEY_free(pkey); return DSA_ERROR; } /* sign the hashvalue of the key */ if (!(EVP_SignFinal(&mdctx, pubkey->sig_buf, &pubkey->sig_len, pkey))) { init_logSslErrors("pers_signKey (EVP_DigestFinal)"); pubkey->sig_len = 0; EVP_PKEY_free(pkey); return DSA_ERROR; } if (pubkey->sig_len > EVP_MAX_MD_SIZE) { log(LOG_ERR, "pers_signKey --> serialised signature exeeds EVP_MAX_MD_SIZE %d / %d.\n", pubkey->sig_len, EVP_MAX_MD_SIZE); EVP_PKEY_free(pkey); return DSA_ERROR; } if (loglevel == LOG_DEBUG) { DSA_SIG *sig; char *bn_buf; sig = NULL; ptr = pubkey->sig_buf; sig = d2i_DSA_SIG(&sig, &ptr, pubkey->sig_len); if ((bn_buf = BN_bn2dec(sig->r))) { log(LOG_DEBUG, "pers_signKey --> signature r (%d bytes): %s\n", strlen(bn_buf), bn_buf); OPENSSL_free(bn_buf); } if ((bn_buf = BN_bn2dec(sig->s))) { log(LOG_DEBUG, "pers_signKey --> signature s (%d bytes): %s\n", strlen(bn_buf), bn_buf); OPENSSL_free(bn_buf); } if ((bn_buf = BN_bn2dec(host_priv_key->p))) { log(LOG_DEBUG, "pers_signKey --> private key p (%d bytes): %s\n", strlen(bn_buf), bn_buf); OPENSSL_free(bn_buf); } if ((bn_buf = BN_bn2dec(host_priv_key->q))) { log(LOG_DEBUG, "pers_signKey --> private key q (%d bytes): %s\n", strlen(bn_buf), bn_buf); OPENSSL_free(bn_buf); } if ((bn_buf = BN_bn2dec(host_priv_key->g))) { log(LOG_DEBUG, "pers_signKey --> private key g (%d bytes): %s\n", strlen(bn_buf), bn_buf); OPENSSL_free(bn_buf); } if ((bn_buf = BN_bn2dec(host_priv_key->priv_key))) { log(LOG_DEBUG, "pers_signKey --> private key x (%d bytes): %s\n", strlen(bn_buf), bn_buf); OPENSSL_free(bn_buf); } } EVP_PKEY_free(pkey); log(LOG_INFO, "pers_signKey --> key %s signed.\n", pubkey->email); return DSA_ACCEPT; } int pers_verifyKey(KEY *pubkey){ EVP_MD_CTX mdctx; /* context for the message digest containing the hash value of the public key to verify */ EVP_PKEY *pkey; /* a pointer on the envelope for the DSA key */ unsigned char key_buf[DSA_BUF_LEN]; /* buffer containing the serialised public key */ unsigned int buf_len; /* variable to store the key length */ int ret; /* the return value of the signature check */ const unsigned char *ptr; /* a pointer on the keybuffer */ pubkey->flags &= ~IS_VERIFIED; /* begin of real procedure */ if (!pubkey->sig_len) { log(LOG_ERR,"pers_verifyKey --> can't verify - no signature in key %s.\n", pubkey->email); return DSA_ERROR; } /* serialise the public key to verify in key_buf memory is allocated and must be freed on error and when finished */ if (!pubkey->dsa) { log(LOG_ERR,"pers_verifyKey --> can't verify - no dsa structure in key %s.\n", pubkey->email); return DSA_ERROR; } /* serialise the public key to verify in key_buf The pointer on this buffer must be a local variable because it will be incremented during the procedure pointing to the address behind key_buf + buf_len */ ptr = key_buf; if ((buf_len = i2d_DSAPublicKey(pubkey->dsa, &ptr)) < 0) { init_logSslErrors("pers_verifyKey (i2d_DSAPublicKey)"); return DSA_ERROR; } if (buf_len > DSA_BUF_LEN) { log(LOG_ERR, "pers_verifyKey --> serialised key exeeds DSA_BUF_LEN %d / %d.\n", buf_len, DSA_BUF_LEN); return DSA_ERROR; } /* initialise the context for hashing with the SHA1 algorithm */ if (!(EVP_VerifyInit(&mdctx, EVP_dss1()))) { init_logSslErrors("pers_verifyKey (EVP_DigestInit)"); return DSA_ERROR; } /* update the context with the serialised key to hash */ if (!(EVP_VerifyUpdate(&mdctx, key_buf, buf_len))) { init_logSslErrors("pers_verifyKey (EVP_DigestUpdate)"); return DSA_ERROR; } if (loglevel == LOG_DEBUG) { DSA_SIG *sig; char *bn_buf; sig = NULL; ptr = pubkey->sig_buf; sig = d2i_DSA_SIG(&sig, &ptr, pubkey->sig_len); if ((bn_buf = BN_bn2dec(sig->r))) { log(LOG_DEBUG, "pers_verifyKey --> signature r (%d bytes): %s\n", strlen(bn_buf), bn_buf); OPENSSL_free(bn_buf); } if ((bn_buf = BN_bn2dec(sig->s))) { log(LOG_DEBUG, "pers_verifyKey --> signature s (%d bytes): %s\n", strlen(bn_buf), bn_buf); OPENSSL_free(bn_buf); } if ((bn_buf = BN_bn2dec(master_pub_key->p))) { log(LOG_DEBUG, "pers_verifyKey --> public key p (%d bytes): %s\n", strlen(bn_buf), bn_buf); OPENSSL_free(bn_buf); } if ((bn_buf = BN_bn2dec(master_pub_key->q))) { log(LOG_DEBUG, "pers_verifyKey --> public key q (%d bytes): %s\n", strlen(bn_buf), bn_buf); OPENSSL_free(bn_buf); } if ((bn_buf = BN_bn2dec(master_pub_key->g))) { log(LOG_DEBUG, "pers_verifyKey --> public key g (%d bytes): %s\n", strlen(bn_buf), bn_buf); OPENSSL_free(bn_buf); } if ((bn_buf = BN_bn2dec(master_pub_key->pub_key))) { log(LOG_DEBUG, "pers_verifyKey --> public key y (g^x) (%d bytes): %s\n", strlen(bn_buf), bn_buf); OPENSSL_free(bn_buf); } } /* create the envelope key */ if (!(pkey = EVP_PKEY_new())) { init_logSslErrors("pers_verifyKey (EVP_PKEY_new)"); return DSA_ERROR; } /* put the public master key into the envelope, don't use EVP_PKEY_assign_DSA or you loose the DSA key too on freeing the EVP_PKEY */ if (!(EVP_PKEY_set1_DSA(pkey, master_pub_key))) { init_logSslErrors("pers_verifyKey (EVP_PKEY_set1_DSA)"); EVP_PKEY_free(pkey); return DSA_ERROR; } ret = EVP_VerifyFinal(&mdctx, pubkey->sig_buf, pubkey->sig_len, pkey); if (ret == DSA_ERROR) { pubkey->sig_len = 0; init_logSslErrors("pers_verifyKey (EVP_DigestFinal)"); EVP_PKEY_free(pkey); return ret; } if (ret == DSA_ACCEPT) { pubkey->flags |= IS_VERIFIED; pubkey->flags &= ~FROM_FILE; log(LOG_INFO, "pers_verifyKey --> key %s verified.\n", pubkey->email); } if (ret == DSA_REJECT) { pubkey->sig_len = 0; log(LOG_INFO, "pers_verifyKey --> key %s rejected.\n", pubkey->email); } EVP_PKEY_free(pkey); return ret; } The logging output of this signing and verifying example is: 21:19:33 pers_signKey --> signature r (48 bytes): 748579810289355699838500268556918127256339752467 21:19:34 pers_signKey --> signature s (48 bytes): 688280662998673456050651939583557489974822517632 21:19:34 pers_signKey --> private key p (155 bytes): 10829692190232787463565838956086206137190348560761908594796749951079376565632981279403369050926864048144229783329236491486421335210727979083380759271655437 21:19:35 pers_signKey --> private key q (48 bytes): 768969016486072524144558170934065416490814812281 21:19:35 pers_signKey --> private key g (154 bytes): 3553173476319000480323849172700953872902743131825941145971353799053654197254289715921211086624613172598558713446689292640459457466917659881927304867195086 21:19:36 pers_signKey --> private key x (48 bytes): 374320894898160993779827061043104060008118291894 21:19:38 pers_signKey --> key thomas.mangold@... signed. 21:19:50 pers_verifyKey --> signature r (48 bytes): 748579810289355699838500268556918127256339752467 21:19:51 pers_verifyKey --> signature s (48 bytes): 688280662998673456050651939583557489974822517632 21:19:51 pers_verifyKey --> public key p (155 bytes): 10829692190232787463565838956086206137190348560761908594796749951079376565632981279403369050926864048144229783329236491486421335210727979083380759271655437 21:19:52 pers_verifyKey --> public key q (48 bytes): 768969016486072524144558170934065416490814812281 21:19:53 pers_verifyKey --> public key g (154 bytes): 3553173476319000480323849172700953872902743131825941145971353799053654197254289715921211086624613172598558713446689292640459457466917659881927304867195086 21:19:54 pers_verifyKey --> public key y (g^x) (154 bytes): 2311195631463402811034457671992662441661460498286972902253094605910543108710915798218219055877819519505658487943208491707682304736152687567269924687159195 21:20:27 pers_verifyKey --> key thomas.mangold@... rejected. There are no errors but the return value of EVP_VerifyFinal() is always 0. The big numbers computed are matching but I could not calculate the algorithm by hand due to integer overflow on every system i tried. Has anyone an idea, what I'm doing wrong? thank you for helping Thomas Mangold ______________________________________________________________________ OpenSSL Project http://www.openssl.org User Support Mailing List openssl-users@... Automated List Manager majordomo@... |
| Free Forum Powered by Nabble | Forum Help |