package Net::DNS::SEC::Private;

#
# $Id: Private.pm 1304 2015-01-26 07:50:36Z willem $
#
use vars qw($VERSION);
$VERSION = (qw$LastChangedRevision: 1304 $)[1];


=head1 NAME

Net::DNS::SEC::Private - DNSSEC Private key object


=head1 SYNOPSIS

    use Net::DNS::SEC::Private;

    $private = new Net::DNS::SEC::Private( $keypath );

    $private = new Net::DNS::SEC::Private(
	'algorithm'  => '13',
	'keytag'     => '26512',
	'privatekey' => 'h/mc+iq9VDUbNAjQgi8S8JzlEX29IALchwJmNM3QYKk=',
	'signame'    => 'example.com.'
	);


=head1 DESCRIPTION

Class representing private keys as read from a keyfile generated by
dnssec-keygen. The class is written to be used only in the context of the
Net::DNS::RR::RRSIG create method. This class is not designed to interact
with any other system.

=cut


use strict;
use integer;
use warnings;
use Carp;
use File::Spec;
use FileHandle;

my $debug = 0;


sub new { scalar(@_) > 2 ? &_new_params : &_new_keyfile }

sub _new_keyfile {
	my ( $class, $file ) = @_;

	my ( $vol, $dir, $keyname ) = File::Spec->splitpath($file);

	print "\nKeyname: $keyname\n" if $debug;

	# Format something like: /Kbla.foo.+001+60114.private'
	# assuming proper file name.
	# We determine the algorithm from the filename.
	croak "$keyname does not appear to be a private key"
			unless $keyname =~ /^K(.*\.)\+(\d+)\+(\d+)\.private$/;
	my @identifier = ( signame => $1, algorithm => 0 + $2, keytag => $3 );

	my $handle = new FileHandle($file) or croak qq(open: "$file" $!);

	my @content;
	local $_;
	while (<$handle>) {
		chomp;
		next if /^$/;
		next if /^\s*[;]/;
		s/\(.+\)//;
		my ( $name, $value ) = split;
		push @content, $name, $value;
	}

	return $class->_new_params( @content, @identifier );
}


sub _new_params {
	my $class = shift;
	my $param = {};
	while (@_) {
		my $name = shift @_;
		$name =~ tr/A-Za-z0-9\000-\377/a-za-z0-9/d;
		$param->{$name} = shift @_;
	}

	my $self = bless sub { $param->{shift()} }, $class;
	croak 'algorithm not defined' unless defined $self->algorithm;
	croak 'signame not defined'   unless defined $self->signame;
	return $self;
}


use vars qw($AUTOLOAD);

sub DESTROY { }				## Avoid tickling AUTOLOAD (in cleanup)

sub AUTOLOAD {				## Default method
	my ($self) = @_;
	no strict q/refs/;

	my ($attribute) = $AUTOLOAD =~ m/::([^:]*)$/;
	$attribute =~ tr/A-Za-z0-9\000-\377/a-za-z0-9/d;

	# Build a method in the class
	*{$AUTOLOAD} = sub {
		my $self = shift;
		&$self($attribute);
	};

	# and jump to it
	goto &{$AUTOLOAD};
}


1;

__END__



=head1 METHODS

=head2 new (from private keyfile)

    $keypath = '/home/foo/Kexample.com.+013+26512.private';
    $private = new Net::DNS::SEC::Private( $keypath );

The argument is the full path to a private key file generated by the
BIND dnssec-keygen tool.  Note that the filename contains information
about the algorithm and keytag.


=head2 new (from private key parameters)

    $private = new Net::DNS::SEC::Private(
	'algorithm'  => '13',
	'keytag'     => '26512',
	'privatekey' => 'h/mc+iq9VDUbNAjQgi8S8JzlEX29IALchwJmNM3QYKk=',
	'signame'    => 'example.com.'
	);

The arguments define the private key parameters as (name,value) pairs.
The name and data representation are identical to that used in a BIND
private keyfile.


=head2 private_key_format

    $format = $private->private_key_format;

Returns a string which identifies the format of the private key file.


=head2 created, publish, activate

    $created  = $private->created;
    $publish  = $private->publish;
    $activate = $private->activate;

Returns a string which represents a date in the form 20141212123456.
Returns undefined value for key formats older than v1.3.


=head2 algorithm, keytag, signame
 
    $algorithm = $private->algorithm;
    $keytag    = $private->keytag;
    $signame   = $private->signame;

Returns the corresponding attribute determined from the filename.


=head2 Private key attributes

    $attribute = $private->attribute;

Returns the value as it appears in the private key file.
The attribute names correspond to the tag in the key file, modified
to form an acceptable Perl subroutine name.


=head1 COPYRIGHT

Copyright (c)2014 Dick Franks

All Rights Reserved

This program is free software; you may redistribute it and/or modify it
under the same terms as Perl itself.


=head1 SEE ALSO

L<perl>, L<Net::DNS>,
L<Net::DNS::RR::RRSIG>, L<Net::DNS::RR::SIG>

=cut

