Crypt-OpenSSL-DSA-0.20/0000755000000000000000000000000014024733511011310 5ustar Crypt-OpenSSL-DSA-0.20/Changes0000644000000000000000000000416314024733203012605 0ustar Revision history for Perl extension Crypt::OpenSSL::DSA. 0.20 2021/03/18 - fix #7 Add function to get signature size - fix #8 Allocate buffer for 2048 bit keys 0.19 2017/01/13 - fix building against openssl 1.1.0 without compat modes (eroen) 0.18 2016/11/17 - OpenSSL 1.1.0 compatibility - fix Kwalitee Issues 0.17 2016/10/27 - Makefile.PL fixing v0.16 0.16 2016/10/27 - Makefile.PL supports OPENSSL_PREFIX or OPENSSL_LIB+OPENSSL_INCLUDE env variables - Makefile.PL tries to find libcrypto via pkg-config - Make the files non-executable - Doc fixes (grammar) 0.15 2015/02/03 - #84367 Win32 compatibility patch - #80369 fix errors in POD. Mainly just missing =over/=back - #80368 Makefile.PL: unneeded -lssl in LIBS 0.14 2012/10/16 - compiling with -Werror=format-security now works (Jerome Quelin, #48446) - Use Digest::SHA instead of Digest::SHA1 (Ansgar Burchardt, #60271) - Security fix, CVE-2009-0129: Missing error check in do_verify (Havard Eidnes, #79958) 0.13 2005/10/15 - made t/90-openssl-compat.t windows compatible (Rob) 0.12 2005/05/22 - Removed all use of strlen() in DSA.xs so signatures with nulls, as commonly generated with sha1, could be signed/verified, and added more tests (Brad Fitzpatrick ) 0.11 2003/01/06 - Added -DPERL5 to Makefile.PL required for perl-5.8/gcc-3.2 0.10 2002/09/25 - Fixed Memory leak with signature object. - Added set_p, set_q, set_g, set_pub_key, set_priv_key (Olaf Kolkman) - Added set_r and set_s methods to Crypt::OpenSSL::DSA::Signature - Renamed Signature.pm to Signature.pod 0.04 2002/09/24 - Fixed bug in verify method - Added read_priv_key_str and read_pub_key_str 0.03 2002/02/06 - Added Crypt::OpenSSL::DSA::Signature interface 0.02 2001/09/24 - Added more docs - seed is now optional argument in generate_parameters 0.01 2001/09/18 - original version; created by h2xs Crypt-OpenSSL-DSA-0.20/DSA.xs0000644000000000000000000004106614024732746012313 0ustar /* $Id: */ #ifdef __cplusplus extern "C" { #endif #include "EXTERN.h" #include "perl.h" #include "XSUB.h" #include #include #include #include #include #include #ifdef __cplusplus } #endif #if OPENSSL_VERSION_NUMBER < 0x10100000L static void DSA_get0_pqg(const DSA *d, const BIGNUM **p, const BIGNUM **q, const BIGNUM **g) { if (p != NULL) *p = d->p; if (q != NULL) *q = d->q; if (g != NULL) *g = d->g; } static int DSA_set0_pqg(DSA *d, BIGNUM *p, BIGNUM *q, BIGNUM *g) { /* If the fields p, q and g in d are NULL, the corresponding input * parameters MUST be non-NULL. */ if ((d->p == NULL && p == NULL) || (d->q == NULL && q == NULL) || (d->g == NULL && g == NULL)) return 0; if (p != NULL) { BN_free(d->p); d->p = p; } if (q != NULL) { BN_free(d->q); d->q = q; } if (g != NULL) { BN_free(d->g); d->g = g; } return 1; } static void DSA_get0_key(const DSA *d, const BIGNUM **pub_key, const BIGNUM **priv_key) { if (pub_key != NULL) *pub_key = d->pub_key; if (priv_key != NULL) *priv_key = d->priv_key; } static int DSA_set0_key(DSA *d, BIGNUM *pub_key, BIGNUM *priv_key) { /* If the field pub_key in d is NULL, the corresponding input * parameters MUST be non-NULL. The priv_key field may * be left NULL. */ if (d->pub_key == NULL && pub_key == NULL) return 0; if (pub_key != NULL) { BN_free(d->pub_key); d->pub_key = pub_key; } if (priv_key != NULL) { BN_free(d->priv_key); d->priv_key = priv_key; } return 1; } static void DSA_SIG_get0(const DSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps) { if (pr != NULL) *pr = sig->r; if (ps != NULL) *ps = sig->s; } static int DSA_SIG_set0(DSA_SIG *sig, BIGNUM *r, BIGNUM *s) { if (r == NULL || s == NULL) return 0; BN_clear_free(sig->r); BN_clear_free(sig->s); sig->r = r; sig->s = s; return 1; } #endif MODULE = Crypt::OpenSSL::DSA PACKAGE = Crypt::OpenSSL::DSA PROTOTYPES: DISABLE BOOT: #if OPENSSL_VERSION_NUMBER < 0x10100000L ERR_load_crypto_strings(); #endif DSA * new(CLASS) char * CLASS CODE: RETVAL = DSA_new(); OUTPUT: RETVAL void DESTROY(dsa) DSA *dsa CODE: DSA_free(dsa); DSA * generate_parameters(CLASS, bits, seed = NULL) char * CLASS int bits SV * seed PREINIT: DSA * dsa; STRLEN seed_len = 0; char * seedpv = NULL; unsigned long err; CODE: if (seed) { seedpv = SvPV(seed, seed_len); } #if OPENSSL_VERSION_NUMBER < 0x10100000L dsa = DSA_generate_parameters(bits, seedpv, (int)seed_len, NULL, NULL, NULL, NULL); if (!dsa) { #else dsa = DSA_new(); if (!DSA_generate_parameters_ex(dsa, bits, seedpv, (int)seed_len, NULL, NULL, NULL)) { #endif err = ERR_get_error(); if (err == 0) { croak("DSA_generate_parameters() returned NULL"); } else { croak("%s", ERR_reason_error_string(err)); } } RETVAL = dsa; OUTPUT: RETVAL int generate_key(dsa) DSA * dsa CODE: RETVAL = DSA_generate_key(dsa); OUTPUT: RETVAL int get_sig_size(dsa) DSA * dsa CODE: RETVAL = DSA_size(dsa); OUTPUT: RETVAL DSA_SIG * do_sign(dsa, dgst) DSA * dsa SV * dgst PREINIT: DSA_SIG * sig; char * CLASS = "Crypt::OpenSSL::DSA::Signature"; char * dgst_pv = NULL; STRLEN dgst_len = 0; CODE: dgst_pv = SvPV(dgst, dgst_len); if (!(sig = DSA_do_sign((const unsigned char *) dgst_pv, (int)dgst_len, dsa))) { croak("Error in dsa_sign: %s",ERR_error_string(ERR_get_error(), NULL)); } RETVAL = sig; OUTPUT: RETVAL SV * sign(dsa, dgst) DSA * dsa SV * dgst PREINIT: unsigned char *sigret; unsigned int siglen; char * dgst_pv = NULL; STRLEN dgst_len = 0; CODE: siglen = DSA_size(dsa); sigret = malloc(siglen); dgst_pv = SvPV(dgst, dgst_len); /* warn("Length of sign [%s] is %d\n", dgst_pv, dgst_len); */ if (!(DSA_sign(0, (const unsigned char *) dgst_pv, (int)dgst_len, sigret, &siglen, dsa))) { croak("Error in DSA_sign: %s",ERR_error_string(ERR_get_error(), NULL)); } RETVAL = newSVpvn(sigret, siglen); free(sigret); OUTPUT: RETVAL int verify(dsa, dgst, sigbuf) DSA * dsa SV *dgst SV *sigbuf PREINIT: char * dgst_pv = NULL; STRLEN dgst_len = 0; char * sig_pv = NULL; STRLEN sig_len = 0; CODE: dgst_pv = SvPV(dgst, dgst_len); sig_pv = SvPV(sigbuf, sig_len); RETVAL = DSA_verify(0, dgst_pv, (int)dgst_len, sig_pv, (int)sig_len, dsa); if (RETVAL == -1) croak("Error in DSA_verify: %s",ERR_error_string(ERR_get_error(), NULL)); OUTPUT: RETVAL int do_verify(dsa, dgst, sig) DSA *dsa SV *dgst DSA_SIG *sig PREINIT: char * dgst_pv = NULL; STRLEN dgst_len = 0; CODE: dgst_pv = SvPV(dgst, dgst_len); RETVAL = DSA_do_verify(dgst_pv, (int)dgst_len, sig, dsa); if (RETVAL == -1) croak("Error in DSA_do_verify: %s",ERR_error_string(ERR_get_error(), NULL)); OUTPUT: RETVAL DSA * read_params(CLASS, filename) char *CLASS char *filename PREINIT: FILE *f; CODE: if(!(f = fopen(filename, "r"))) croak("Can't open file %s", filename); RETVAL = PEM_read_DSAparams(f, NULL, NULL, NULL); fclose(f); OUTPUT: RETVAL int write_params(dsa, filename) DSA * dsa char *filename PREINIT: FILE *f; CODE: if(!(f = fopen(filename, "w"))) croak("Can't open file %s", filename); RETVAL = PEM_write_DSAparams(f, dsa); fclose(f); OUTPUT: RETVAL DSA * _load_key(CLASS, private_flag_SV, key_string_SV) char *CLASS; SV * private_flag_SV; SV * key_string_SV; PREINIT: STRLEN key_string_length; /* Needed to pass to SvPV */ char *key_string; char private_flag; BIO *stringBIO; CODE: private_flag = SvTRUE( private_flag_SV ); key_string = SvPV( key_string_SV, key_string_length ); if( (stringBIO = BIO_new_mem_buf(key_string, (int)key_string_length)) == NULL ) croak( "Failed to create memory BIO %s", ERR_error_string(ERR_get_error(), NULL)); RETVAL = private_flag ? PEM_read_bio_DSAPrivateKey( stringBIO, NULL, NULL, NULL ) : PEM_read_bio_DSA_PUBKEY( stringBIO, NULL, NULL, NULL ); BIO_set_close(stringBIO, BIO_CLOSE); BIO_free( stringBIO ); if ( RETVAL == NULL ) croak( "Failed to read key %s", ERR_error_string(ERR_get_error(), NULL)); OUTPUT: RETVAL DSA * read_pub_key(CLASS, filename) char *CLASS char *filename PREINIT: FILE *f; CODE: if(!(f = fopen(filename, "r"))) croak("Can't open file %s", filename); RETVAL = PEM_read_DSA_PUBKEY(f, NULL, NULL, NULL); fclose(f); OUTPUT: RETVAL int write_pub_key(dsa, filename) DSA * dsa char *filename PREINIT: FILE *f; CODE: if(!(f = fopen(filename, "w"))) croak("Can't open file %s", filename); RETVAL = PEM_write_DSA_PUBKEY(f, dsa); fclose(f); OUTPUT: RETVAL DSA * read_priv_key(CLASS, filename) char *CLASS char *filename PREINIT: FILE *f; CODE: if(!(f = fopen(filename, "r"))) croak("Can't open file %s", filename); RETVAL = PEM_read_DSAPrivateKey(f, NULL, NULL, NULL); fclose(f); OUTPUT: RETVAL int write_priv_key(dsa, filename) DSA * dsa char *filename PREINIT: FILE *f; CODE: if(!(f = fopen(filename, "w"))) croak("Can't open file %s", filename); RETVAL = PEM_write_DSAPrivateKey(f, dsa, NULL, NULL, 0, NULL, NULL); fclose(f); OUTPUT: RETVAL SV * get_p(dsa) DSA *dsa PREINIT: const BIGNUM *p; char *to; int len; int bnlen; CODE: DSA_get0_pqg(dsa, &p, NULL, NULL); bnlen = BN_num_bytes(p); to = malloc(sizeof(char) * bnlen); len = BN_bn2bin(p, to); RETVAL = newSVpvn(to, len); free(to); OUTPUT: RETVAL SV * get_q(dsa) DSA *dsa PREINIT: const BIGNUM *q; char *to; int len; int bnlen; CODE: DSA_get0_pqg(dsa, NULL, &q, NULL); bnlen = BN_num_bytes(q); to = malloc(sizeof(char) * bnlen); len = BN_bn2bin(q, to); RETVAL = newSVpvn(to, len); free(to); OUTPUT: RETVAL SV * get_g(dsa) DSA *dsa PREINIT: const BIGNUM *g; char *to; int len; int bnlen; CODE: DSA_get0_pqg(dsa, NULL, NULL, &g); bnlen = BN_num_bytes(g); to = malloc(sizeof(char) * bnlen); len = BN_bn2bin(g, to); RETVAL = newSVpvn(to, len); free(to); OUTPUT: RETVAL SV * get_pub_key(dsa) DSA *dsa PREINIT: const BIGNUM *pub_key; char *to; int len; int bnlen; CODE: DSA_get0_key(dsa, &pub_key, NULL); bnlen = BN_num_bytes(pub_key); to = malloc(sizeof(char) * bnlen); len = BN_bn2bin(pub_key, to); RETVAL = newSVpvn(to, len); free(to); OUTPUT: RETVAL SV * get_priv_key(dsa) DSA *dsa PREINIT: const BIGNUM *priv_key; char *to; int len; int bnlen; CODE: DSA_get0_key(dsa, NULL, &priv_key); bnlen = BN_num_bytes(priv_key); to = malloc(sizeof(char) * bnlen); len = BN_bn2bin(priv_key, to); RETVAL = newSVpvn(to, len); free(to); OUTPUT: RETVAL void set_p(dsa, p_SV) DSA *dsa SV * p_SV PREINIT: STRLEN len; BIGNUM *p; BIGNUM *q; BIGNUM *g; const BIGNUM *old_q; const BIGNUM *old_g; CODE: len = SvCUR(p_SV); p = BN_bin2bn(SvPV(p_SV, len), (int)len, NULL); DSA_get0_pqg(dsa, NULL, &old_q, &old_g); if (NULL == old_q) { q = BN_new(); } else { q = BN_dup(old_q); } if (NULL == q) { BN_free(p); croak("Could not duplicate another prime"); } if (NULL == old_g) { g = BN_new(); } else { g = BN_dup(old_g); } if (NULL == g) { BN_free(p); BN_free(q); croak("Could not duplicate another prime"); } if (!DSA_set0_pqg(dsa, p, q, g)) { BN_free(p); BN_free(q); BN_free(g); croak("Could not set a prime"); } void set_q(dsa, q_SV) DSA *dsa SV * q_SV PREINIT: STRLEN len; BIGNUM *p; BIGNUM *q; BIGNUM *g; const BIGNUM *old_p; const BIGNUM *old_g; CODE: len = SvCUR(q_SV); q = BN_bin2bn(SvPV(q_SV, len), (int)len, NULL); DSA_get0_pqg(dsa, &old_p, NULL, &old_g); if (NULL == old_p) { p = BN_new(); } else { p = BN_dup(old_p); } if (NULL == p) { BN_free(q); croak("Could not duplicate another prime"); } if (NULL == old_g) { g = BN_new(); } else { g = BN_dup(old_g); } if (NULL == g) { BN_free(p); BN_free(q); croak("Could not duplicate another prime"); } if (!DSA_set0_pqg(dsa, p, q, g)) { BN_free(p); BN_free(q); BN_free(g); croak("Could not set a prime"); } void set_g(dsa, g_SV) DSA *dsa SV * g_SV PREINIT: STRLEN len; BIGNUM *p; BIGNUM *q; BIGNUM *g; const BIGNUM *old_p; const BIGNUM *old_q; CODE: len = SvCUR(g_SV); g = BN_bin2bn(SvPV(g_SV, len), (int)len, NULL); DSA_get0_pqg(dsa, &old_p, &old_q, NULL); if (NULL == old_p) { p = BN_new(); } else { p = BN_dup(old_p); } if (NULL == p) { BN_free(g); croak("Could not duplicate another prime"); } if (NULL == old_q) { q = BN_new(); } else { q = BN_dup(old_q); } if (NULL == q) { BN_free(p); BN_free(g); croak("Could not duplicate another prime"); } if (!DSA_set0_pqg(dsa, p, q, g)) { BN_free(p); BN_free(q); BN_free(g); croak("Could not set a prime"); } void set_pub_key(dsa, pub_key_SV) DSA *dsa SV * pub_key_SV PREINIT: STRLEN len; BIGNUM *pub_key; CODE: len = SvCUR(pub_key_SV); pub_key = BN_bin2bn(SvPV(pub_key_SV, len), (int)len, NULL); if (!DSA_set0_key(dsa, pub_key, NULL)) { BN_free(pub_key); croak("Could not set a key"); } void set_priv_key(dsa, priv_key_SV) DSA *dsa SV * priv_key_SV PREINIT: STRLEN len; const BIGNUM *old_pub_key; BIGNUM *pub_key; BIGNUM *priv_key; CODE: DSA_get0_key(dsa, &old_pub_key, NULL); if (NULL == old_pub_key) { pub_key = BN_new(); if (NULL == pub_key) { croak("Could not create a dummy public key"); } if (!DSA_set0_key(dsa, pub_key, NULL)) { BN_free(pub_key); croak("Could not set a dummy public key"); } } len = SvCUR(priv_key_SV); priv_key = BN_bin2bn(SvPV(priv_key_SV, len), (int)len, NULL); if (!DSA_set0_key(dsa, NULL, priv_key)) { BN_free(priv_key); croak("Could not set a key"); } MODULE = Crypt::OpenSSL::DSA PACKAGE = Crypt::OpenSSL::DSA::Signature DSA_SIG * new(CLASS) char * CLASS CODE: RETVAL = DSA_SIG_new(); OUTPUT: RETVAL void DESTROY(dsa_sig) DSA_SIG *dsa_sig CODE: DSA_SIG_free(dsa_sig); SV * get_r(dsa_sig) DSA_SIG *dsa_sig PREINIT: const BIGNUM *r; char *to; int len; int bnlen; CODE: DSA_SIG_get0(dsa_sig, &r, NULL); bnlen = BN_num_bytes(r); to = malloc(sizeof(char) * bnlen); len = BN_bn2bin(r, to); RETVAL = newSVpvn(to, len); free(to); OUTPUT: RETVAL SV * get_s(dsa_sig) DSA_SIG *dsa_sig PREINIT: const BIGNUM *s; char *to; int len; int bnlen; CODE: DSA_SIG_get0(dsa_sig, NULL, &s); bnlen = BN_num_bytes(s); to = malloc(sizeof(char) * bnlen); len = BN_bn2bin(s, to); RETVAL = newSVpvn(to, len); free(to); OUTPUT: RETVAL void set_r(dsa_sig, r_SV) DSA_SIG *dsa_sig SV * r_SV PREINIT: STRLEN len; BIGNUM *r; BIGNUM *s; const BIGNUM *old_s; CODE: len = SvCUR(r_SV); r = BN_bin2bn(SvPV(r_SV, len), (int)len, NULL); DSA_SIG_get0(dsa_sig, NULL, &old_s); if (NULL == old_s) { s = BN_new(); } else { s = BN_dup(old_s); } if (NULL == s) { BN_free(r); croak("Could not duplicate another signature value"); } if (!DSA_SIG_set0(dsa_sig, r, s)) { BN_free(r); BN_free(s); croak("Could not set a signature"); } void set_s(dsa_sig, s_SV) DSA_SIG *dsa_sig SV * s_SV PREINIT: STRLEN len; BIGNUM *s; BIGNUM *r; const BIGNUM *old_r; CODE: len = SvCUR(s_SV); s = BN_bin2bn(SvPV(s_SV, len), (int)len, NULL); DSA_SIG_get0(dsa_sig, &old_r, NULL); if (NULL == old_r) { r = BN_new(); } else { r = BN_dup(old_r); } if (NULL == r) { BN_free(s); croak("Could not duplicate another signature value"); } if (!DSA_SIG_set0(dsa_sig, r, s)) { BN_free(s); croak("Could not set a signature"); } Crypt-OpenSSL-DSA-0.20/lib/0000755000000000000000000000000014024733503012057 5ustar Crypt-OpenSSL-DSA-0.20/lib/Crypt/0000755000000000000000000000000014024733503013160 5ustar Crypt-OpenSSL-DSA-0.20/lib/Crypt/OpenSSL/0000755000000000000000000000000014024733503014443 5ustar Crypt-OpenSSL-DSA-0.20/lib/Crypt/OpenSSL/DSA/0000755000000000000000000000000014024733503015052 5ustar Crypt-OpenSSL-DSA-0.20/lib/Crypt/OpenSSL/DSA/Signature.pod0000644000000000000000000000227614024732746017536 0ustar =head1 NAME Crypt::OpenSSL::DSA::Signature - Digital Signature Object =head1 SYNOPSIS use Crypt::OpenSSL::DSA; my $dsa_priv = Crypt::OpenSSL::DSA->read_priv_key( $filename ); my $sig_obj = $dsa_priv->do_sign($message); my $dsa_pub = Crypt::OpenSSL::DSA->read_pub_key( $filename ); my $valid = $dsa_pub->do_verify($message, $sig_obj); my $sig_size = $dsa_priv->get_sig_size(); my $r = $sig_obj->get_r; my $s = $sig_obj->get_s; my $sig_obj2 = Crypt::OpenSSL::DSA::Signature->new(); $sig_obj2->set_r($r); $sig_obj2->set_s($s); my $valid = $dsa_pub->do_verify($message, $sig_obj2); =head1 CLASS METHODS =over =item $sig_obj = Crypt::OpenSSL::DSA::Signature->new(); Create a new DSA Signature Object. You will need to call set_r and set_s after you create this. =back =head1 OBJECT METHODS =over =item $r = $sig_obj->get_r; Gets first member of signature pair. =item $s = $sig_obj->get_s; Gets second member of signature pair. =item $r = $sig_obj->set_r; Sets first member of signature pair. =item $s = $sig_obj->set_s; Sets second member of signature pair. =back =head1 AUTHOR T.J. Mather, Etjmather@maxmind.comE =head1 SEE ALSO L =cut Crypt-OpenSSL-DSA-0.20/lib/Crypt/OpenSSL/DSA.pm0000644000000000000000000001360114024733224015411 0ustar package Crypt::OpenSSL::DSA; use strict; use warnings; require DynaLoader; use vars qw(@ISA $VERSION); @ISA = qw(DynaLoader); $VERSION = '0.20'; bootstrap Crypt::OpenSSL::DSA $VERSION; sub read_pub_key_str { my ($class, $key_str) = @_; $class->_load_key(0, $key_str); } sub read_priv_key_str { my ($class, $key_str) = @_; $class->_load_key(1, $key_str); } 1; __END__ =head1 NAME Crypt::OpenSSL::DSA - Digital Signature Algorithm using OpenSSL =head1 SYNOPSIS use Crypt::OpenSSL::DSA; # generate keys and write out to PEM files my $dsa = Crypt::OpenSSL::DSA->generate_parameters( 512 ); $dsa->generate_key; $dsa->write_pub_key( $filename ); $dsa->write_priv_key( $filename ); # using keys from PEM files my $dsa_priv = Crypt::OpenSSL::DSA->read_priv_key( $filename ); my $sig = $dsa_priv->sign($message); my $dsa_pub = Crypt::OpenSSL::DSA->read_pub_key( $filename ); my $valid = $dsa_pub->verify($message, $sig); # using keys from PEM strings my $dsa_priv = Crypt::OpenSSL::DSA->read_priv_key_str( $key_string ); my $sig = $dsa_priv->sign($message); my $dsa_pub = Crypt::OpenSSL::DSA->read_pub_key_str( $key_string ); my $valid = $dsa_pub->verify($message, $sig); =head1 DESCRIPTION Crypt::OpenSSL::DSA implements the DSA (Digital Signature Algorithm) signature verification system. It is a thin XS wrapper to the DSA functions contained in the OpenSSL crypto library, located at http://www.openssl.org =head1 CLASS METHODS =over 4 =item $dsa = Crypt::OpenSSL::DSA->generate_parameters( $bits, $seed ); Returns a new DSA object and generates the p, q and g parameters necessary to generate keys. bits is the length of the prime to be generated; the DSS allows a maximum of 1024 bits. =item $dsa = Crypt::OpenSSL::DSA->read_params( $filename ); Reads in a parameter PEM file and returns a new DSA object with the p, q and g parameters necessary to generate keys. =item $dsa = Crypt::OpenSSL::DSA->read_pub_key( $filename ); Reads in a public key PEM file and returns a new DSA object that can be used to verify DSA signatures. =item $dsa = Crypt::OpenSSL::DSA->read_priv_key( $filename ); Reads in a private key PEM file and returns a new DSA object that can be used to sign messages. =item $dsa = Crypt::OpenSSL::DSA->read_pub_key_str( $key_string ); Reads in a public key PEM string and returns a new DSA object that can be used to verify DSA signatures. The string should include the -----BEGIN...----- and -----END...----- lines. =item $dsa = Crypt::OpenSSL::DSA->read_priv_key_str( $key_string ); Reads in a private key PEM string and returns a new DSA object that can be used to sign messages. The string should include the -----BEGIN...----- and -----END...----- lines. =back =head1 OBJECT METHODS =over 4 =item $dsa->generate_key; Generates private and public keys, assuming that $dsa is the return value of generate_parameters. =item $sig_size = $dsa->get_sig_size( ); Returns the maximum size of an ASN.1 encoded DSA signature for key dsa in bytes. 512-bit keys = 48 1024-bit keys = 48 2024-bit keys = 72 3072-bit keys = 72 ASN.1 dsa signatures consist of: Sequence 1-byte (0x30) Length 1-byte Integer 1-byte (0x02) Length 1-byte (0x14) = 20 r 20-bytes or 21-bytes Integer 1-byte (0x02) Length 1-byte (0x14) = 20 s 20-bytes or 21-bytes 30 2C 02 14 6C.70.50.7C.93.A8.B5.EC.1E.A1.5E.C5.73.AA.0F.EA.4D.BE.42.7A 02 14 4E.AD.E6.BB.72.54.92.30.2B.03.AB.53.5D.3D.6E.88.B8.AA.D6.30 Note that the above signature is 46 bytes long - the extra two bytes are used only when r and/or s are larger than or equal to 2^159. The extra bytes are used to distinguish positive from negative values. All that to say if you are using get_sig_size() to determine the size of r + s depending on the size of the key you can subtract 8 bytes for the ASN.1 overhead. =item $sig = $dsa->sign( $message ); Signs $message, returning the signature. Note that $meesage cannot exceed 20 characters in length. $dsa is the signer's private key. =item $sig_obj = $dsa->do_sign( $message ); Similar to C, but returns a L object. =item $valid = $dsa->verify( $message, $sig ); Verifies that the $sig signature for $message is valid. $dsa is the signer's public key. Note: it croaks if the underlying library call returns error (-1). =item $valid = $dsa->do_verify( $message, $sig_obj ); Similar to C, but uses a L object. Note: it croaks if the underlying library call returns error (-1). =item $dsa->write_params( $filename ); Writes the parameters into a PEM file. =item $dsa->write_pub_key( $filename ); Writes the public key into a PEM file. =item $dsa->write_priv_key( $filename ); Writes the private key into a PEM file. =item $p = $dsa->get_p, $dsa->set_p($p) Gets/sets the prime number in binary format. =item $q = $dsa->get_q, $dsa->set_q($q) Gets/sets the subprime number (q | p-1) in binary format. =item $g = $dsa->get_g, $dsa->set_g($g) Gets/sets the generator of subgroup in binary format. =item $pub_key = $dsa->get_pub_key, $dsa->set_pub_key($pub_key) Gets/sets the public key (y = g^x) in binary format. =item $priv_key = $dsa->get_priv_key, $dsa->set_priv_key($priv_key) Gets/sets the private key in binary format. =back =head1 NOTES L is a more mature Perl DSA module, but can be difficult to install, because of the L requirement. Comments, suggestions, and patches welcome. =head1 AUTHOR T.J. Mather, Etjmather@maxmind.comE =head1 COPYRIGHT Copyright (c) 2002 T.J. Mather. Crypt::OpenSSL::DSA is free software; you may redistribute it and/or modify it under the same terms as Perl itself. Paid support is available directly from the author of this package. Please see L for more details. =head1 SEE ALSO L L, L L =cut Crypt-OpenSSL-DSA-0.20/LICENSE0000755000000000000000000000015413002643145012316 0ustar This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.Crypt-OpenSSL-DSA-0.20/Makefile.PL0000644000000000000000000000235713036106351013267 0ustar use strict; use warnings; use Config; use ExtUtils::MakeMaker; my $lib = '-lcrypto'; my $inc = ''; my $nul = $^O eq 'MSWin32' ? 'nul' : '/dev/null'; if (my $dir = $ENV{OPENSSL_PREFIX}) { $lib = "-L$dir/lib -lcrypto"; $inc = "-I$dir/include"; } elsif ($ENV{OPENSSL_LIB}) { $lib = $ENV{OPENSSL_LIB}; $inc = $ENV{OPENSSL_INCLUDE}; } elsif (`pkg-config --modversion libcrypto 2>$nul`) { $lib = `pkg-config --libs libcrypto 2> $nul`; $inc = `pkg-config --cflags libcrypto 2> $nul`; } elsif ($^O eq 'MSWin32') { $lib = '-llibeay32' if $Config{cc} =~ /cl/; $lib = '-leay32' if $Config{cc} =~ /gcc/; } WriteMakefile( 'NAME' => 'Crypt::OpenSSL::DSA', 'VERSION_FROM' => 'lib/Crypt/OpenSSL/DSA.pm', # finds $VERSION 'LICENSE' => 'perl_5', 'MIN_PERL_VERSION' => '5.006', 'PREREQ_PM' => {}, # e.g., Module::Name => 1.1 'AUTHOR' => 'T.J. Mather', 'LIBS' => [ $lib ], 'INC' => $inc, 'DEFINE' => '-DPERL5', # perl-5.8/gcc-3.2 needs this 'META_MERGE' => { resources => { repository => 'https://github.com/kmx/perl-Crypt-OpenSSL-DSA', }, }, dist => { TARFLAGS => '--owner=0 --group=0 -cvf' }, ); Crypt-OpenSSL-DSA-0.20/MANIFEST0000644000000000000000000000052114024733511012437 0ustar Changes DSA.xs lib/Crypt/OpenSSL/DSA.pm lib/Crypt/OpenSSL/DSA/Signature.pod LICENSE Makefile.PL MANIFEST README t/00-use.t t/10-selftest.t t/90-openssl-compat.t typemap META.yml Module YAML meta-data (added by MakeMaker) META.json Module JSON meta-data (added by MakeMaker) Crypt-OpenSSL-DSA-0.20/META.json0000644000000000000000000000176414024733511012741 0ustar { "abstract" : "unknown", "author" : [ "T.J. Mather" ], "dynamic_config" : 1, "generated_by" : "ExtUtils::MakeMaker version 7.58, CPAN::Meta::Converter version 2.150010", "license" : [ "perl_5" ], "meta-spec" : { "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", "version" : 2 }, "name" : "Crypt-OpenSSL-DSA", "no_index" : { "directory" : [ "t", "inc" ] }, "prereqs" : { "build" : { "requires" : { "ExtUtils::MakeMaker" : "0" } }, "configure" : { "requires" : { "ExtUtils::MakeMaker" : "0" } }, "runtime" : { "requires" : { "perl" : "5.006" } } }, "release_status" : "stable", "resources" : { "repository" : { "url" : "https://github.com/kmx/perl-Crypt-OpenSSL-DSA" } }, "version" : "0.20", "x_serialization_backend" : "JSON::PP version 4.05" } Crypt-OpenSSL-DSA-0.20/META.yml0000644000000000000000000000111214024733505012557 0ustar --- abstract: unknown author: - 'T.J. Mather' build_requires: ExtUtils::MakeMaker: '0' configure_requires: ExtUtils::MakeMaker: '0' dynamic_config: 1 generated_by: 'ExtUtils::MakeMaker version 7.58, CPAN::Meta::Converter version 2.150010' license: perl meta-spec: url: http://module-build.sourceforge.net/META-spec-v1.4.html version: '1.4' name: Crypt-OpenSSL-DSA no_index: directory: - t - inc requires: perl: '5.006' resources: repository: https://github.com/kmx/perl-Crypt-OpenSSL-DSA version: '0.20' x_serialization_backend: 'CPAN::Meta::YAML version 0.018' Crypt-OpenSSL-DSA-0.20/README0000644000000000000000000000150013013276452012167 0ustar Crypt::OpenSSL::DSA =================== DESCRIPTION Crypt::OpenSSL::DSA implements the DSA (Digital Signature Algorithm) signature verification system. It is a thin XS wrapper to the DSA functions contained in the OpenSSL crypto library, located at http://www.openssl.org INSTALLATION To install this module type the following: perl Makefile.PL make make test make install DEPENDENCIES This module requires these other modules and libraries: openssl, available from http://www.openssl.org/ COPYRIGHT AND LICENCE Copyright (c) 2002 T.J. Mather. Crypt::OpenSSL::DSA is free software; you may redistribute it and/or modify it under the same terms as Perl itself. Paid support is available directly from the author of this package. Please see http://www.maxmind.com/app/opensourceservices for more details. Crypt-OpenSSL-DSA-0.20/t/0000755000000000000000000000000014024733503011554 5ustar Crypt-OpenSSL-DSA-0.20/t/00-use.t0000644000000000000000000000056213004361462012753 0ustar # -*- Mode: Perl; -*- # test file added by Brad Fitzpatrick in response to bugs found by Karl Koscher # related to null bytes in SHA1 signatures, and strlen truncating the message # being signed/verified use strict; use Test; use Crypt::OpenSSL::DSA; BEGIN { plan tests => 1 }; my $dsa = Crypt::OpenSSL::DSA->generate_parameters( 512 ); $dsa->generate_key; ok(1); Crypt-OpenSSL-DSA-0.20/t/10-selftest.t0000644000000000000000000000630213006127506014010 0ustar # -*- Mode: Perl; -*- use strict; use Test; use Crypt::OpenSSL::DSA; BEGIN { plan tests => 36 } my $message = "foo bar"; my $dsa = Crypt::OpenSSL::DSA->generate_parameters( 512, "fooooooooooooooooooo" ); $dsa->generate_key; my $dsa_sig1 = $dsa->sign($message); my $dsa_sig_obj1 = $dsa->do_sign($message); my $bogus_sig = $dsa_sig1; $bogus_sig =~ s!.a$!ba!; $bogus_sig =~ s!.$!a!; my $p = $dsa->get_p; my $q = $dsa->get_q; my $g = $dsa->get_g; my $pub_key = $dsa->get_pub_key; my $priv_key = $dsa->get_priv_key; my $r = $dsa_sig_obj1->get_r; my $s = $dsa_sig_obj1->get_s; my $dsa_sig_obj2 = Crypt::OpenSSL::DSA::Signature->new(); $dsa_sig_obj2->set_r($r); $dsa_sig_obj2->set_s($s); my $dsa_sig_obj_bogus = Crypt::OpenSSL::DSA::Signature->new(); $dsa_sig_obj_bogus->set_r($s); $dsa_sig_obj_bogus->set_s($r); ok($dsa->verify($message, $dsa_sig1), 1); ok($dsa->verify($message, $bogus_sig), 0); ok($dsa->do_verify($message, $dsa_sig_obj1), 1); ok($dsa->do_verify($message, $dsa_sig_obj2), 1); ok($dsa->do_verify($message, $dsa_sig_obj_bogus), 0); ok($dsa->write_params("dsa.param.pem"), 1); ok($dsa->write_pub_key("dsa.pub.pem"), 1); ok($dsa->write_priv_key("dsa.priv.pem"), 1); my ($priv_key_str, $pub_key_str); { local($/) = undef; open PRIV, "dsa.priv.pem"; $priv_key_str = ; close PRIV; open PUB, "dsa.pub.pem"; $pub_key_str = ; close PUB; } my $dsa2 = Crypt::OpenSSL::DSA->read_priv_key("dsa.priv.pem"); my $dsa_sig2 = $dsa2->sign($message); my $dsa3 = Crypt::OpenSSL::DSA->read_pub_key("dsa.pub.pem"); my $dsa4 = Crypt::OpenSSL::DSA->read_priv_key_str($priv_key_str); my $dsa5 = Crypt::OpenSSL::DSA->read_pub_key_str($pub_key_str); my $dsa6 = Crypt::OpenSSL::DSA->new(); $dsa6->set_p($p); $dsa6->set_q($q); $dsa6->set_g($g); $dsa6->set_pub_key($pub_key); ok($dsa6->get_p,$p); ok($dsa6->get_q,$q); ok($dsa6->get_g,$g); ok($dsa6->get_pub_key,$pub_key); ok($dsa->verify($message, $dsa_sig2), 1); ok($dsa2->verify($message, $dsa_sig2), 1); ok($dsa2->verify($message, $dsa_sig1), 1); ok($dsa3->verify($message, $dsa_sig1), 1); ok($dsa3->verify($message, $dsa_sig2), 1); ok($dsa4->verify($message, $dsa_sig2), 1); ok($dsa4->verify($message, $dsa_sig1), 1); ok($dsa5->verify($message, $dsa_sig1), 1); ok($dsa5->verify($message, $dsa_sig2), 1); ok($dsa6->verify($message, $dsa_sig1), 1); ok($dsa6->verify($message, $dsa_sig2), 1); $dsa6->set_priv_key($priv_key); ok($dsa6->get_priv_key,$priv_key); my $dsa_sig3 = $dsa6->sign($message); ok($dsa->verify($message, $dsa_sig3), 1); ok($dsa2->verify($message, $dsa_sig3), 1); ok($dsa3->verify($message, $dsa_sig3), 1); ok($dsa4->verify($message, $dsa_sig3), 1); ok($dsa5->verify($message, $dsa_sig3), 1); ok($dsa6->verify($message, $dsa_sig3), 1); # Check setting private key before public key. # This is not suppored by OpenSSL-1.1.0. my $dsa7 = Crypt::OpenSSL::DSA->new(); $dsa7->set_p($p); $dsa7->set_q($q); $dsa7->set_g($g); ok($dsa7->get_p,$p); ok($dsa7->get_q,$q); ok($dsa7->get_g,$g); $dsa7->set_priv_key($priv_key); ok($dsa7->get_priv_key,$priv_key); my $dsa_sig4 = $dsa7->sign($message); $dsa7->set_pub_key($pub_key); ok($dsa7->get_pub_key,$pub_key); ok($dsa7->verify($message, $dsa_sig4), 1); unlink("dsa.param.pem"); unlink("dsa.priv.pem"); unlink("dsa.pub.pem"); Crypt-OpenSSL-DSA-0.20/t/90-openssl-compat.t0000644000000000000000000000451413006127475015143 0ustar # -*- Mode: Perl; -*- # test file added by Brad Fitzpatrick in response to bugs found by Karl Koscher # related to null bytes in SHA1 signatures, and strlen truncating the message # being signed/verified use strict; use Test; use Crypt::OpenSSL::DSA; BEGIN { plan tests => 84 } my $HAS_SHA1 = eval "use Digest::SHA; 1;"; my ($OPEN_SSL, $testable); if($^O !~ /mswin32/i) { $OPEN_SSL = `which openssl` || "/usr/bin/openssl"; chomp $OPEN_SSL; $testable = -x $OPEN_SSL && $HAS_SHA1; } else { $OPEN_SSL = "openssl"; eval{`openssl version`}; if(!$@) {$testable = 1 && $HAS_SHA1} } my $why_skip = $HAS_SHA1 ? "Need openssl binary in path" : "Need Digest::SHA to test"; my $dsa = Crypt::OpenSSL::DSA->generate_parameters( 512, "fooooooooooooooooooo" ); $dsa->generate_key; ok($dsa->write_pub_key("dsa.pub.pem"), 1); ok($dsa->write_priv_key("dsa.priv.pem"), 1); my $dsa_pub = Crypt::OpenSSL::DSA->read_pub_key("dsa.pub.pem"); ok($dsa_pub); my $dsa_priv = Crypt::OpenSSL::DSA->read_priv_key("dsa.priv.pem"); ok($dsa_priv); my $to_do = 500; my $of_each = 20; if ($testable) { my %done; # { zero => $ct, nonzero => $ct } for (1..$to_do) { my $plain = "This is test number $_"; my $msg = Digest::SHA::sha1($plain); my $type = ($msg =~ /\x00/) ? "zero" : "nonzero"; next if $done{$type}++ >= $of_each; my $sig = $dsa_priv->sign($msg); my $we_think = $dsa_pub->verify($msg, $sig); my $openssl_think = openssl_verify("dsa.pub.pem", $sig, $plain); ok($we_think, 1); ok($openssl_think, 1); } } else { for (1..($of_each*4)) { print "ok # Skip $why_skip\n"; } } unlink("dsa.priv.pem"); unlink("dsa.pub.pem"); sub openssl_verify { my ($public_pem_file, $sig, $msg_plain) = @_; require File::Temp; my $sig_temp = new File::Temp(TEMPLATE => "tmp.signatureXXXX") or die; my $msg_temp = new File::Temp(TEMPLATE => "tmp.msgXXXX") or die; syswrite($sig_temp,$sig); syswrite($msg_temp,$msg_plain); # FIXME: shutup openssl from spewing to STDOUT the "Verification # OK". can we depend on reading "Verification OK" from the # open("-|", "openssl") open mode due to portability? my $rv = system("openssl", "dgst", "-sha1", "-verify", $public_pem_file, "-signature", "$sig_temp", "$msg_temp"); return 0 if $rv; return 1; } Crypt-OpenSSL-DSA-0.20/typemap0000644000000000000000000000100613004361462012706 0ustar TYPEMAP DSA * O_OBJECT DSA_SIG * O_OBJECT INPUT O_OBJECT if( sv_isobject($arg) && (SvTYPE(SvRV($arg)) == SVt_PVMG) ) $var = INT2PTR($type, SvIV((SV*)SvRV( $arg ))); else{ warn( \"${Package}::$func_name() -- $var is not a blessed SV reference\" ); XSRETURN_UNDEF; } OUTPUT # The Perl object is blessed into 'CLASS', which should be a # char* having the name of the package for the blessing. O_OBJECT sv_setref_pv( $arg, (char *)CLASS, (void*)$var );