File Coverage

blib/lib/Monero/Keys.pm
Criterion Covered Total %
statement 170 170 100.0
branch 7 8 87.5
condition n/a
subroutine 9 9 100.0
pod 1 4 25.0
total 187 191 97.9


line stmt bran cond sub pod time code
1             package Monero::Keys;
2              
3 1     1   228335 use strict;
  1         2  
  1         61  
4 1     1   13 use warnings;
  1         4  
  1         94  
5 1     1   827 use Crypt::Digest::Keccak256 qw(keccak256);
  1         10199  
  1         79  
6 1     1   1663 use Math::BigInt;
  1         88866  
  1         5  
7              
8             our $VERSION = '0.04';
9              
10             require XSLoader;
11             XSLoader::load('Monero::Keys', $VERSION);
12              
13             sub load3 {
14 48     48 0 122 my ($b, $index) = @_;
15 48         154 my $result = substr($b, $index, 3) . "\x0";
16 48         299 return Math::BigInt->new(unpack("V", $result));
17             }
18              
19             sub load4 {
20 48     48 0 128 my ($b, $index) = @_;
21 48         121 my $result = substr($b, $index, 4);
22 48         241 return Math::BigInt->new(unpack("V", $result));
23             }
24              
25             sub sc_reduce {
26 8     8 0 27 my ($b) = @_;
27 8         39 my $s0 = 2097151 & load3($b, 0);
28 8         3697 my $s1 = 2097151 & (load4($b, 2) >> 5);
29 8         6832 my $s2 = 2097151 & (load3($b, 5) >> 2);
30 8         6251 my $s3 = 2097151 & (load4($b, 7) >> 7);
31 8         6245 my $s4 = 2097151 & (load4($b, 10) >> 4);
32 8         6473 my $s5 = 2097151 & (load3($b, 13) >> 1);
33 8         5550 my $s6 = 2097151 & (load4($b, 15) >> 6);
34 8         6348 my $s7 = 2097151 & (load3($b, 18) >> 3);
35 8         5914 my $s8 = 2097151 & load3($b, 21);
36 8         2974 my $s9 = 2097151 & (load4($b, 23) >> 5);
37 8         5986 my $s10 = 2097151 & (load3($b, 26) >> 2);
38 8         5823 my $s11 = load4($b, 28) >> 7;
39 8         4129 my $s12 = 0;
40              
41 8         41 my $carry0 = ($s0 + (1 << 20)) >> 21; $s1 += $carry0; $s0 -= $carry0 << 21;
  8         6720  
  8         1069  
42 8         3948 my $carry2 = ($s2 + (1 << 20)) >> 21; $s3 += $carry2; $s2 -= $carry2 << 21;
  8         6473  
  8         1005  
43 8         3857 my $carry4 = ($s4 + (1 << 20)) >> 21; $s5 += $carry4; $s4 -= $carry4 << 21;
  8         6486  
  8         1024  
44 8         3763 my $carry6 = ($s6 + (1 << 20)) >> 21; $s7 += $carry6; $s6 -= $carry6 << 21;
  8         6537  
  8         912  
45 8         3520 my $carry8 = ($s8 + (1 << 20)) >> 21; $s9 += $carry8; $s8 -= $carry8 << 21;
  8         6456  
  8         924  
46 8         3274 my $carry10 = ($s10 + (1 << 20)) >> 21; $s11 += $carry10; $s10 -= $carry10 << 21;
  8         6411  
  8         996  
47              
48 8         3617 my $carry1 = ($s1 + (1 << 20)) >> 21; $s2 += $carry1; $s1 -= $carry1 << 21;
  8         6433  
  8         1007  
49 8         3386 my $carry3 = ($s3 + (1 << 20)) >> 21; $s4 += $carry3; $s3 -= $carry3 << 21;
  8         6461  
  8         1005  
50 8         3691 my $carry5 = ($s5 + (1 << 20)) >> 21; $s6 += $carry5; $s5 -= $carry5 << 21;
  8         6388  
  8         1068  
51 8         3920 my $carry7 = ($s7 + (1 << 20)) >> 21; $s8 += $carry7; $s7 -= $carry7 << 21;
  8         6349  
  8         942  
52 8         3910 my $carry9 = ($s9 + (1 << 20)) >> 21; $s10 += $carry9; $s9 -= $carry9 << 21;
  8         6395  
  8         1006  
53 8         3490 my $carry11 = ($s11 + (1 << 20)) >> 21; $s12 += $carry11; $s11 -= $carry11 << 21;
  8         6492  
  8         2448  
54              
55 8         4059 $s0 += $s12 * 666643;
56 8         3644 $s1 += $s12 * 470296;
57 8         3430 $s2 += $s12 * 654183;
58 8         3426 $s3 -= $s12 * 997805;
59 8         3483 $s4 += $s12 * 136657;
60 8         3270 $s5 -= $s12 * 683901;
61 8         3605 $s12 = 0;
62              
63 8         36 $carry0 = $s0 >> 21; $s1 += $carry0; $s0 -= $carry0 << 21;
  8         3548  
  8         1025  
64 8         4102 $carry1 = $s1 >> 21; $s2 += $carry1; $s1 -= $carry1 << 21;
  8         3299  
  8         1057  
65 8         3774 $carry2 = $s2 >> 21; $s3 += $carry2; $s2 -= $carry2 << 21;
  8         3368  
  8         1058  
66 8         3996 $carry3 = $s3 >> 21; $s4 += $carry3; $s3 -= $carry3 << 21;
  8         3266  
  8         1038  
67 8         4130 $carry4 = $s4 >> 21; $s5 += $carry4; $s4 -= $carry4 << 21;
  8         3373  
  8         1019  
68 8         3484 $carry5 = $s5 >> 21; $s6 += $carry5; $s5 -= $carry5 << 21;
  8         3132  
  8         983  
69 8         4183 $carry6 = $s6 >> 21; $s7 += $carry6; $s6 -= $carry6 << 21;
  8         3080  
  8         1039  
70 8         3311 $carry7 = $s7 >> 21; $s8 += $carry7; $s7 -= $carry7 << 21;
  8         2975  
  8         1047  
71 8         3744 $carry8 = $s8 >> 21; $s9 += $carry8; $s8 -= $carry8 << 21;
  8         3059  
  8         995  
72 8         3185 $carry9 = $s9 >> 21; $s10 += $carry9; $s9 -= $carry9 << 21;
  8         3026  
  8         942  
73 8         3641 $carry10 = $s10 >> 21; $s11 += $carry10; $s10 -= $carry10 << 21;
  8         2949  
  8         1023  
74 8         3613 $carry11 = $s11 >> 21; $s12 += $carry11; $s11 -= $carry11 << 21;
  8         3013  
  8         2611  
75              
76 8         3145 $s0 += $s12 * 666643;
77 8         3467 $s1 += $s12 * 470296;
78 8         3314 $s2 += $s12 * 654183;
79 8         3215 $s3 -= $s12 * 997805;
80 8         3552 $s4 += $s12 * 136657;
81 8         3268 $s5 -= $s12 * 683901;
82              
83 8         3625 $carry0 = $s0 >> 21; $s1 += $carry0; $s0 -= $carry0 << 21;
  8         3351  
  8         881  
84 8         3096 $carry1 = $s1 >> 21; $s2 += $carry1; $s1 -= $carry1 << 21;
  8         3069  
  8         896  
85 8         3044 $carry2 = $s2 >> 21; $s3 += $carry2; $s2 -= $carry2 << 21;
  8         3032  
  8         923  
86 8         3082 $carry3 = $s3 >> 21; $s4 += $carry3; $s3 -= $carry3 << 21;
  8         3010  
  8         876  
87 8         3054 $carry4 = $s4 >> 21; $s5 += $carry4; $s4 -= $carry4 << 21;
  8         3096  
  8         900  
88 8         2859 $carry5 = $s5 >> 21; $s6 += $carry5; $s5 -= $carry5 << 21;
  8         3211  
  8         898  
89 8         3121 $carry6 = $s6 >> 21; $s7 += $carry6; $s6 -= $carry6 << 21;
  8         3099  
  8         871  
90 8         2902 $carry7 = $s7 >> 21; $s8 += $carry7; $s7 -= $carry7 << 21;
  8         3162  
  8         878  
91 8         2868 $carry8 = $s8 >> 21; $s9 += $carry8; $s8 -= $carry8 << 21;
  8         3192  
  8         875  
92 8         2888 $carry9 = $s9 >> 21; $s10 += $carry9; $s9 -= $carry9 << 21;
  8         3137  
  8         924  
93 8         2871 $carry10 = $s10 >> 21; $s11 += $carry10; $s10 -= $carry10 << 21;
  8         3233  
  8         889  
94 8         2938 $DB::single = 1;
95 8         32 my @items = (
96             $s0 >> 0,
97             $s0 >> 8,
98             ($s0 >> 16) | ($s1 << 5),
99             $s1 >> 3,
100             $s1 >> 11,
101             ($s1 >> 19) | ($s2 << 2),
102             $s2 >> 6,
103             ($s2 >> 14) | ($s3 << 7),
104             $s3 >> 1,
105             $s3 >> 9,
106             ($s3 >> 17) | ($s4 << 4),
107             $s4 >> 4,
108             $s4 >> 12,
109             ($s4 >> 20) | ($s5 << 1),
110             $s5 >> 7,
111             ($s5 >> 15) | ($s6 << 6),
112             $s6 >> 2,
113             $s6 >> 10,
114             ($s6 >> 18) | ($s7 << 3),
115             $s7 >> 5,
116             $s7 >> 13,
117             $s8 >> 0,
118             $s8 >> 8,
119             ($s8 >> 16) | ($s9 << 5),
120             $s9 >> 3,
121             $s9 >> 11,
122             ($s9 >> 19) | ($s10 << 2),
123             $s10 >> 6,
124             ($s10 >> 14) | ($s11 << 7),
125             $s11 >> 1,
126             $s11 >> 9,
127             $s11 >> 17
128             );
129              
130 8         130963 my $newb = '';
131 8         25 for my $i (@items) {
132 256         101977 $newb .= chr($i & 0xFF);
133             }
134 8         3668 return $newb;
135             }
136              
137             sub _is_not_zero {
138 8     8   22 my $b = shift;
139 8         33 for my $i (0..31) {
140 71 100       226 return 1 if ord(substr($b, $i, 1)) != 0;
141             }
142 2         18 return 0;
143             }
144              
145             sub generate_keys {
146 5     5 1 236701 my $seed = shift;
147 5 100       27 if (length($seed) < 32) {
148 1         46 $seed .= "\x00" x (32 - length($seed));
149             }
150 5         21 my $spend_pk = sc_reduce($seed);
151 5         22183 my $spend_pub = _generate_pk_from_sk($spend_pk);
152 5 100       34 return undef unless _is_not_zero($spend_pk);
153 3         20 my $keccak = keccak256($spend_pk);
154 3         125 my $view_pk = sc_reduce($keccak);
155 3 50       17 return undef unless _is_not_zero($view_pk);
156             return {
157 3         13327 spend_pk => $spend_pk,
158             spend_pub => $spend_pub,
159             view_pk => $view_pk,
160             view_pub => _generate_pk_from_sk($view_pk),
161             };
162             }
163             # Preloaded methods go here.
164              
165             1;
166             __END__