package Crypt::Perl::ECDSA::EncodedPoint; use strict; use warnings; use Try::Tiny; use Crypt::Perl::ECDSA::Utils (); use Crypt::Perl::X (); #input can be a string or BigInt, #in any of “hybrid”, “uncompressed”, or “compressed” formats sub new { my ($class, $input) = @_; my $bin; my $input_is_obj; if ( try { $input->isa('Crypt::Perl::BigInt') } ) { $bin = $input->as_bytes(); $input_is_obj = 1; } else { $input =~ s<\A\0+><>; $bin = $input; } my $first_octet = ord substr( $bin, 0, 1 ); my $self = bless {}, $class; #Accommodate “hybrid” points if ($first_octet == 6 || $first_octet == 7) { $self->{'_bin'} = "\x04" . substr( $bin, 1 ); } elsif ($first_octet == 4) { $self->{'_bin'} = $bin; } elsif ($first_octet == 2 || $first_octet == 3) { $self->{'_compressed_bin'} = $bin; } else { die Crypt::Perl::X::Create('Generic', sprintf "Invalid leading octet in ECDSA point: %v02x", $bin); } return $self; } #returns a string sub get_compressed { my ($self) = @_; return $self->{'_compressed_bin'} ||= do { Crypt::Perl::ECDSA::Utils::compress_point( $self->{'_bin'} ); }; } #returns a string sub get_uncompressed { my ($self, $curve_hr) = @_; die "Need curve! (p, a, b)" if !$curve_hr; return $self->{'_bin'} ||= do { die "Need compressed bin!" if !$self->{'_compressed_bin'}; Crypt::Perl::ECDSA::Utils::decompress_point( $self->{'_compressed_bin'}, @{$curve_hr}{ qw( p a b ) }, ); }; } #If there’s ever a demand for “hybrid”: #0x06 and 0x07 take the place of the uncompressed leading 0x04, #analogous to 0x02 and 0x03 in the compressed form. 1;