File Coverage

blib/lib/Blockchain/Ethereum/Keystore/Key/PKUtil.pm
Criterion Covered Total %
statement 11 39 28.2
branch 0 8 0.0
condition n/a
subroutine 4 5 80.0
pod n/a
total 15 52 28.8


line stmt bran cond sub pod time code
1 3     3   47 use v5.26;
  3         12  
2 3     3   26 use Object::Pad;
  3         7  
  3         38  
3              
4             package Blockchain::Ethereum::Keystore::Key::PKUtil;
5             class Blockchain::Ethereum::Keystore::Key::PKUtil
6 3     3   2188 :isa(Crypt::Perl::ECDSA::PrivateKey);
  3         77609  
  3         186  
7              
8             our $AUTHORITY = 'cpan:REFECO'; # AUTHORITY
9             our $VERSION = '0.006'; # VERSION
10              
11 3     3   814 use Carp;
  3         8  
  3         2633  
12              
13 0     0     method _sign ($message) {
  0            
  0            
  0            
14              
15 0           my $dgst = Crypt::Perl::BigInt->from_bytes($message);
16              
17 0           my $priv_num = $self->{'private'}; # Math::BigInt->from_hex( $priv_hex );
18              
19 0           my $n = $self->_curve()->{'n'};
20              
21 0           my $key_len = $self->max_sign_bits();
22 0           my $dgst_len = $dgst->bit_length();
23 0 0         if ($dgst_len > $key_len) {
24 0           croak Crypt::Perl::X::create('TooLongToSign', $key_len, $dgst_len);
25             }
26              
27             #isa ECPoint
28 0           my $G = $self->_G();
29 0           my ($k, $r, $Q);
30              
31 0           do {
32 0           require Crypt::Perl::ECDSA::Deterministic;
33 0           $k = Crypt::Perl::ECDSA::Deterministic::generate_k($n, $priv_num, $message, 'sha256');
34              
35             # making it external so I can calculate the y parity
36 0           $Q = $G->multiply($k); #$Q isa ECPoint
37              
38 0           $r = $Q->get_x()->to_bigint()->copy()->bmod($n);
39             } while (!$r->is_positive());
40              
41 0           my $s = $k->bmodinv($n);
42              
43             #$s *= ( $dgst + ( $priv_num * $r ) );
44 0           $s->bmul($priv_num->copy()->bmuladd($r, $dgst));
45              
46 0           $s->bmod($n);
47              
48             # y parity calculation
49             # most of the changes unrelated to the parent module are bellow
50 0 0         my $y_parity = ($Q->get_y->to_bigint->is_odd() ? 1 : 0) | ($Q->get_x->to_bigint->bcmp($r) != 0 ? 2 : 0);
    0          
51              
52 0           my $nb2;
53 0           ($nb2, $_) = $n->copy->bdiv(2);
54              
55 0 0         if ($s->bcmp($nb2) > 0) {
56 0           $s = $n->copy->bsub($s);
57 0           $y_parity ^= 1;
58             }
59              
60 0           return ($r, $s, $y_parity);
61             }
62              
63             1;
64              
65             __END__
66              
67             =pod
68              
69             =encoding UTF-8
70              
71             =head1 NAME
72              
73             Blockchain::Ethereum::Keystore::Key::PKUtil
74              
75             =head1 VERSION
76              
77             version 0.006
78              
79             =head1 OVERVIEW
80              
81             This is a child for L<Crypt::Perl::ECDSA::PrivateKey> to overwrite
82             the function _sign that on the parent module returns only C<$r> and C<$s>,
83             this version returns the C<$y_parity> as well, what simplifies signing
84             the transaction.
85              
86             You don't want to use this directly, use instead L<Blockchain::Ethereum::Keystore::Key>
87              
88             =head1 METHODS
89              
90             =head2 _sign
91              
92             Overwrites L<Crypt::Perl::ECDSA::PrivateKey> adding the y-parity to the response
93              
94             =over 4
95              
96             =item * C<message> - Message to be signed
97              
98             =back
99              
100             L<Crypt::Perl::BigInt> r, L<Crypt::Perl::BigInt> s, uint y_parity
101              
102             =head1 AUTHOR
103              
104             Reginaldo Costa <refeco@cpan.org>
105              
106             =head1 COPYRIGHT AND LICENSE
107              
108             This software is Copyright (c) 2023 by REFECO.
109              
110             This is free software, licensed under:
111              
112             The MIT (X11) License
113              
114             =cut