using the DSA signature algorithm of OpenSSL

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



I wanna use the DSA signature algorithms of OpenSSL to verify RRSIG and DNSKEY DNSSEC resource records. This is described in RFC2536 (a very short RFC). As far as I could try it out (see my attachement) there are two ways to sign and verify with OpenSSL/DSA: via the EVP interface and via the DSA interface directly. If I try to sign with one method and verify with the other that fails. What standards do these methods conform to, what is the difference between them and what do I need for my purpose? Also I have found two different ways to create a DSA key yielding apparently different results (see the sample code). Basically for me it is about verifying signatures, not about creating such signatures.

<<program output:>>
(pub)key: 3081F13081A906072A8648CE38040130819D024100EECFDC5C3B730FE9D0A3D25C4B8EF27A7F93D7A8A0047065DB55D881A40CC11A620D65C5BD3A720D187300B25A59E051CCB203BBE13731FC7E65B6371D1CFDD9021500B6334A5665A680A9D017C760CFDEF2FD1FECF6A90241008D7623CF35A041F469B32EDA37ECF551485154047E11FE10DA003FEAB1DF88007860C1F0AE32990B29B52EE6DB6BAFDF1A7FF9FD76CFD5B417861ABE3782F4C3034300024019A7A450C6FE998742DF5D3E0F59C2E9D7D90D6861DA6E912AEB66BCA202FFBE981A381414213BB5504B582AC27A1ACFB8B203366A076BCCF179FC471C2E4CB7
asn1 repr of pubkey is the same
signed message: (method #1, DSA interface)
302C02146F4A174CF347EF3FD2796D1858CADBD4A033DA1F02147DA2FB1329E82509C699806D92BB0713272C1651
signed message: 46 Bytes
signature valid
signed message: (method #2, EVP interface)
302C02142F5296C21FA0956049F124A58621084ADF680BB402140BDD997234B82C901999FA096EFB697D864086BD
signed message: 46 Bytes
authentic  			(verified with the same method)
invalid signature		(verified with the other first method)
#include <string.h>
#include <stdio.h>
#include <openssl/dsa.h>
#include <openssl/ssl.h>
#include <assert.h>

#ifndef INCL

typedef unsigned char uchar;
typedef int bool;
#define true 1
#define false 0

enum PrnHexFlags { PRNHEX_NOSEP = 1 };

void prn_as_hex(FILE *out, const char *message, const uchar *digest, int len, int flags ) { int i;
  bool prnsep; prnsep=!(flags&PRNHEX_NOSEP);
  fprintf(out,message); for( i=0; i<len;i++) fprintf(out,i&&prnsep?":%02X":"%02X",digest[i]); fputc('\n',out); 
}

EVP_PKEY* generate_DSA_key(int bits) {
  // build parameters first
  EVP_PKEY_CTX *ctx_params = EVP_PKEY_CTX_new_id(EVP_PKEY_DSA, NULL);
  EVP_PKEY_CTX_set_dsa_paramgen_bits(ctx_params, bits);
  EVP_PKEY_paramgen_init(ctx_params);

  EVP_PKEY* pkey_params = NULL;
  EVP_PKEY_paramgen(ctx_params, &pkey_params);

  // using parameters, build DSA keypair
  EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new(pkey_params, NULL);
  EVP_PKEY_keygen_init(ctx);

  EVP_PKEY* pkey = NULL;
  EVP_PKEY_keygen(ctx, &pkey);

  // cleanup everything but the final key
  EVP_PKEY_free(pkey_params);
  EVP_PKEY_CTX_free(ctx_params);
  EVP_PKEY_CTX_free(ctx);

  return pkey;
  // f.i.:
  //DSA* dsa = EVP_PKEY_get1_DSA(pkey);
  //BIO* bio = BIO_new_fp(stdout, BIO_NOCLOSE);
  //PEM_write_bio_DSAPrivateKey(bio, dsa, NULL, NULL, 0, NULL, NULL);
  //BIO_flush(bio);
  //DSA_free(dsa);
}

#endif

int main(int argc, char *argv[]) {
  const char *msg = "Hello world!"; int msglen, res; size_t sign_msglen_; uchar *signed_msg, *signed_msg_;
  EVP_PKEY *privkey, *pubkey; int authstatus; //uchar *pbkraw; size_t pbklen;
  EVP_MD_CTX *signctx, *verifyctx; DSA *dsakey; uint sign_msglen;
  int len, len_; uchar *keyptr, *asn1key, *asn1key_;
  //const BIGNUM *pubkey_bn; uchar *bnbuf; int bnbuflen; 

  OPENSSL_init(); OpenSSL_add_all_algorithms();
  //netwcomm_init();
  msglen=strlen(msg);
  //privkey = generate_DSA_key(71);   // 128 -> 2*223

  // assert false:
  //res = EVP_PKEY_get_raw_public_key(privkey,NULL,&pbklen); assert(res>0);
  //pbkraw = (uchar*)malloc(pbklen);
  //res = EVP_PKEY_get_raw_public_key(privkey,pbkraw,&pbklen); assert(res>0);
  
  //EVP_PKEY_print_private(stdout_bio,privkey,0,NULL);  // print_public does not do anything else

  //EVP_PKEY_assign_RSA(pkey, rsa);  PKEY := DSA-key
  //dsakey = EVP_PKEY_get0_DSA(privkey);
  dsakey = DSA_new();
  res = DSA_generate_parameters_ex(dsakey,71,NULL,0,NULL,NULL,NULL); assert(res>0);
  res = DSA_generate_key(dsakey); assert(res>0);
  privkey = EVP_PKEY_new();
  EVP_PKEY_assign_DSA(privkey,dsakey);
  len = i2d_DSA_PUBKEY(dsakey,NULL); keyptr = asn1key = alloca(len); len = i2d_DSA_PUBKEY(dsakey,&keyptr);
  len_ = i2d_PUBKEY(privkey,NULL); keyptr = asn1key_ = alloca(len_); len_ = i2d_PUBKEY(privkey,&keyptr);
  prn_as_hex(stdout,"(pub)key: ", asn1key, len, PRNHEX_NOSEP );
  if(len==len_&&!memcmp(asn1key,asn1key_,len)) printf("asn1 repr of pubkey is the same\n");

  //i2d_DSAPrivateKey

  //DSA_sign_setup();
  DSA_sign(0, (uchar*)msg, msglen, NULL, &sign_msglen, dsakey );
  signed_msg = (uchar*)malloc(sign_msglen);
  DSA_sign(0, (uchar*)msg, msglen, signed_msg, &sign_msglen, dsakey );
  prn_as_hex(stdout,"signed message: ", signed_msg, sign_msglen, PRNHEX_NOSEP );
  printf("signed message: %i Bytes\n", sign_msglen);
  authstatus = DSA_verify(0, (uchar*)msg, msglen, signed_msg, sign_msglen, dsakey );
  if(authstatus==1) printf("signature valid\n"); 
  else if(authstatus==0) printf("invalid signature\n");
  else printf("error at signature verification\n");  // -1
 
  //pubkey_bn = DSA_get0_pub_key(dsakey);
  //bnbuf = alloca(bnbuflen=BN_num_bytes(pubkey_bn));
  //BN_bn2bin(pubkey_bn,bnbuf);
  //prn_as_hex(stdout," pubkey2bin: ", bnbuf,bnbuflen,PRNHEX_NOSEP);
  //printf(" pubkey2bin: %i Bytes\n",bnbuflen);

  signctx = EVP_MD_CTX_create();
  res = EVP_DigestSignInit( signctx, NULL, EVP_sha1(), NULL, privkey ); assert(res>0);
  res = EVP_DigestSignUpdate( signctx, msg, msglen ); assert(res>0);
  res = EVP_DigestSignFinal( signctx, NULL, &sign_msglen_ ); assert(res>0);
  signed_msg_ = (uchar*)malloc(sign_msglen_);
  res = EVP_DigestSignFinal( signctx, signed_msg_, &sign_msglen_ );
  EVP_MD_CTX_free(signctx);
  
  prn_as_hex(stdout,"signed message: ", signed_msg_, sign_msglen_, PRNHEX_NOSEP );
  printf("signed message: %li Bytes\n", sign_msglen_);

  pubkey = privkey;
  verifyctx = EVP_MD_CTX_create();
  res = EVP_DigestVerifyInit( verifyctx, NULL, EVP_sha1(), NULL, pubkey ); assert(res>0);
  res = EVP_DigestVerifyUpdate( verifyctx, msg, msglen ); assert(res>0);
  authstatus = EVP_DigestVerifyFinal( verifyctx, signed_msg_, sign_msglen_ );
  if (authstatus==1) printf("authentic\n");
  else if(authstatus==0) printf("not authentic (0)\n");
  else printf("error at signature verification\n");
  EVP_MD_CTX_free(verifyctx);

  authstatus = DSA_verify(0, (uchar*)msg, msglen, signed_msg_, sign_msglen_, dsakey );
  if(authstatus==1) printf("signature valid\n"); 
  else if(authstatus==0) printf("invalid signature\n");
  else printf("error at signature verification\n");  // -1

  putchar('\n');
  free(signed_msg);
  free(signed_msg_);
  DSA_free(dsakey);
  //EVP_PKEY_free(privkey);
  //netwcomm_cleanup();
  return 0;
}


[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Index of Archives]     [Linux ARM Kernel]     [Linux ARM]     [Linux Omap]     [Fedora ARM]     [IETF Annouce]     [Security]     [Bugtraq]     [Linux]     [Linux OMAP]     [Linux MIPS]     [ECOS]     [Asterisk Internet PBX]     [Linux API]

  Powered by Linux