I've written a dkim-signing filter for opensmtpd that works well. I decided to add the ability to create key pairs and print out the dns entries, etc, etc. Anyway the following code works. Albeit needs some cleaning up. However, it only works if the files already exist.

sub create_keys { my @selectors; my @towrite; eval { require Crypt::OpenSSL::RSA; require Crypt::OpenSSL::Random; foreach my $domain (keys %keys) { my $keyfile = $keys{$domain}->{key}; my $pubfile = $keyfile =~ s/key/pub/g; my $selector = $keys{$domain}->{selector}; Crypt::OpenSSL::RSA->import_random_seed(); my $rsa = Crypt::OpenSSL::RSA->generate_key(1024); my $pub_string = $rsa->get_public_key_string(); my $key_string = $rsa->get_private_key_string(); my $select_string = "-----BEGIN DNS ENTRIES FOR $domain--- +--\n"; $select_string .= "_domainkey IN TXT \"o=~;\"\n\n"; $pub_string =~ s/-----BEGIN\ RSA\ PUBLIC\ KEY-----//g; $pub_string =~ s/-----END\ RSA\ PUBLIC\ KEY-----//g; $pub_string =~ s/\s//g; $select_string .= "$selector\._domainkey IN TXT \"k=rsa\\; +\n"; $select_string .= "p=$pub_string\\;\"\n"; $select_string .= "-----END DNS ENTRIES FOR $domain-----\n +"; push @selectors, $select_string; push @towrite, { key => $keyfile, pub => $pubfile, keystring => $key_string, pubstring => $pub_string }; } }; die "Failed to create keypair: $@" if $@; # moved this out of the eval just to see if that would change anything foreach my $write (@towrite) { { open (my $key, ">", $write->{key}) or die "$!"; print $key $write->{keystring}; open (my $pub, ">", $write->{pub}) or die "$!"; print $pub $write->{pubstring}; } } foreach my $s (@selectors) { print $s . "\n"; } exit 0; }

Here is some sample output:

-----BEGIN DNS ENTRIES FOR domain.tld----- _domainkey IN TXT "o=~;" dkim._domainkey IN TXT "k=rsa\; p=MIGJAoGBAKghtMMxSlhU973zhV29hc0xeppV76jQmdLoIV/Zz9wJw6OenVU4dFWaT5gz +ENe3ufSxkbSOOmGKl5ukurpvPXtoymoD7DcVkU02HDApzmVgwHpT4E/A22SoGxuNwqFrh +VTmwb4gdSVGOKnkUIgeXelDsoG2F22FgnxWjjH03u/FAgMBAAE=\;" -----END DNS ENTRIES FOR domain.tld----- -----BEGIN DNS ENTRIES FOR domain.stuff.tld----- _domainkey IN TXT "o=~;" dkim._domainkey IN TXT "k=rsa\; p=MIGJAoGBAMAxZ3sixzpuON9XQu+zVzJknyJ6sQcJGZxpHKDTz2QG7V5Hpno3jXHYrHqf +nJ+pDtw7IloAT6zYe4DAsFyTbj1/96r1eRubL8DnU59mtxQAQmyoOVa0hiyJss6RTq49Z +dXuVhF0bqqvgrBS51ErkddACBz5F2TxfkO/qli6boL3AgMBAAE=\;" -----END DNS ENTRIES FOR domain.stuff.tld-----

This is what I get if the files don't already exist:
Error: cannot read /home/edgar/domain.stuff.tld.key: No such file or directory

This of course works:
perl -e 'open (my $fh, ">", "/home/edgar/domain.test.key") or die "$!";'
And creates a 0 length file.


In reply to can't open file for writing that doesn't exist by navalned

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.