1package Crypt::Perl::ECDSA::EncodedPoint; 2 3use strict; 4use warnings; 5 6use Try::Tiny; 7 8use Crypt::Perl::ECDSA::Utils (); 9use Crypt::Perl::X (); 10 11#input can be a string or BigInt, 12#in any of “hybrid”, “uncompressed”, or “compressed” formats 13sub new { 14 my ($class, $input) = @_; 15 16 my $bin; 17 18 my $input_is_obj; 19 if ( try { $input->isa('Crypt::Perl::BigInt') } ) { 20 $bin = $input->as_bytes(); 21 $input_is_obj = 1; 22 } 23 else { 24 $input =~ s<\A\0+><>; 25 $bin = $input; 26 } 27 28 my $first_octet = ord substr( $bin, 0, 1 ); 29 30 my $self = bless {}, $class; 31 32 #Accommodate “hybrid” points 33 if ($first_octet == 6 || $first_octet == 7) { 34 $self->{'_bin'} = "\x04" . substr( $bin, 1 ); 35 } 36 elsif ($first_octet == 4) { 37 $self->{'_bin'} = $bin; 38 } 39 elsif ($first_octet == 2 || $first_octet == 3) { 40 $self->{'_compressed_bin'} = $bin; 41 } 42 else { 43 die Crypt::Perl::X::Create('Generic', sprintf "Invalid leading octet in ECDSA point: %v02x", $bin); 44 } 45 46 return $self; 47} 48 49#returns a string 50sub get_compressed { 51 my ($self) = @_; 52 53 return $self->{'_compressed_bin'} ||= do { 54 Crypt::Perl::ECDSA::Utils::compress_point( $self->{'_bin'} ); 55 }; 56} 57 58#returns a string 59sub get_uncompressed { 60 my ($self, $curve_hr) = @_; 61 62 die "Need curve! (p, a, b)" if !$curve_hr; 63 64 return $self->{'_bin'} ||= do { 65 die "Need compressed bin!" if !$self->{'_compressed_bin'}; 66 67 Crypt::Perl::ECDSA::Utils::decompress_point( 68 $self->{'_compressed_bin'}, 69 @{$curve_hr}{ qw( p a b ) }, 70 ); 71 }; 72} 73 74#If there’s ever a demand for “hybrid”: 75#0x06 and 0x07 take the place of the uncompressed leading 0x04, 76#analogous to 0x02 and 0x03 in the compressed form. 77 781; 79