release 0.013_1
Karel Miko
10 years ago
0 | 0 | Changes for CryptX |
1 | 1 | |
2 | 2 | TODO: |
3 | before 0.014: | |
4 | - Crypt::PK::DH/ECC - sign/verify replaced by sign_message/verify_message + sign_hash/verify_hash | |
5 | - Crypt::PK::DH/ECC - new method key2hash | |
6 | later: | |
3 | 7 | - consider: RSA->check_key, RSA password protected keys |
4 | 8 | - consider: PK->encrypt|decrypt ... add 'armour' param and make it compatible with Crypt::RSA |
5 | 9 | - croak with the "real caller" (Crypt::Mac::*, Crypt::Mode::*, ...) |
11 | 15 | RSA: my $k = Crypt::PK::RSA->new; $k->generate_key(256, 65537); |
12 | 16 | - "libtom-src/bn_mp_invmod.c", line 37: warning: statement not reached |
13 | 17 | |
14 | 0.014 2013/09/11 | |
18 | 0.013_1 2013/09/11 | |
15 | 19 | - Crypt::Digest::NNN + Crypt::Mac::NNN - can produce Base64-URL-Safe encoded digest/mac |
16 | 20 | - Crypt::PRNG + Crypt::PRNG::NNN - Base64-URL-Safe encoded random bytes (random_bytes_b64u/bytes_b64u) |
17 | 21 | - Crypt::PK::RSA/DSA - sign/verify replaced by sign_message/verify_message + sign_hash/verify_hash |
22 | - Crypt::PK::RSA/DSA - new method key2hash | |
18 | 23 | - documentation fixes |
19 | 24 | |
20 | 25 | 0.013 2013/08/28 |
71 | 71 | return $self->_decrypt($data); |
72 | 72 | } |
73 | 73 | |
74 | sub _truncate { | |
75 | my ($self, $hash) = @_; | |
76 | ### section 4.6 of FIPS 186-4 | |
77 | # let N be the bit length of q | |
78 | # z = the leftmost min(N, outlen) bits of Hash(M). | |
79 | my $q = $self->size_q; # = size in bytes | |
80 | return $hash if $q >= length($hash); | |
81 | return substr($hash, 0, $q); | |
82 | } | |
83 | ||
74 | 84 | sub sign_message { |
75 | 85 | my ($self, $data, $hash_name) = @_; |
76 | 86 | $hash_name ||= 'SHA1'; |
77 | 87 | my $data_hash = digest_data($hash_name, $data); |
78 | #XXX truncation | |
79 | return $self->_sign($data_hash); | |
88 | return $self->_sign($self->_truncate($data_hash)); | |
80 | 89 | } |
81 | 90 | |
82 | 91 | sub sign_hash { |
83 | 92 | my ($self, $data_hash) = @_; |
84 | #XXX truncation | |
85 | return $self->_sign($data_hash); | |
93 | return $self->_sign($self->_truncate($data_hash)); | |
86 | 94 | } |
87 | 95 | |
88 | 96 | sub verify_message { |
89 | 97 | my ($self, $sig, $data, $hash_name) = @_; |
90 | 98 | $hash_name ||= 'SHA1'; |
91 | 99 | my $data_hash = digest_data($hash_name, $data); |
92 | #XXX truncation | |
93 | return $self->_verify($sig, $data_hash); | |
100 | return $self->_verify($sig, $self->_truncate($data_hash)); | |
94 | 101 | } |
95 | 102 | |
96 | 103 | sub verify_hash { |
97 | 104 | my ($self, $sig, $data_hash) = @_; |
98 | #XXX truncation | |
99 | return $self->_verify($sig, $data_hash); | |
105 | return $self->_verify($sig, $self->_truncate($data_hash)); | |
100 | 106 | } |
101 | 107 | |
102 | 108 | ### FUNCTIONS |
359 | 365 | |
360 | 366 | my $size = $pk->is_private; |
361 | 367 | # returns key size in bytes or undef if no key loaded |
368 | ||
369 | =head2 key2hash | |
370 | ||
371 | my $hash = $pk->key2hash; | |
372 | ||
373 | returns hash like this (or undef if no key loaded): | |
374 | { | |
375 | type => 1, # integer: 1 .. private, 0 .. public | |
376 | qord => 30, # integer: order of the sub-group | |
377 | # all the rest are hex strings | |
378 | g => "847E8896D12C9BF18FE283AE7AD58ED7F3...", #generator | |
379 | p => "AAF839A764E04D80824B79FA1F0496C093...", #prime used to generate the sub-group | |
380 | q => "D05C4CB45F29D353442F1FEC43A6BE2BE8...", #large prime that generats the field the contains the sub-group | |
381 | x => "6C801901AC74E2DC714D75A9F6969483CF...", #private key | |
382 | y => "8F7604D77FA62C7539562458A63C7611B7...", #public key | |
383 | } |
431 | 431 | |
432 | 432 | my $size = $pk->is_private; |
433 | 433 | # returns key size in bytes or undef if no key loaded |
434 | ||
435 | =head2 key2hash | |
436 | ||
437 | my $hash = $pk->key2hash; | |
438 | ||
439 | returns hash like this (or undef if no key loaded): | |
440 | { | |
441 | type => 1, # integer: 1 .. private, 0 .. public | |
442 | # all the rest are hex strings | |
443 | e => "10001", #public exponent | |
444 | d => "9ED5C3D3F866E06957CA0E9478A273C39BBDA4EEAC5B...", #private exponent | |
445 | N => "D0A5CCCAE03DF9C2F5C4C8C0CE840D62CDE279990DC6...", #modulus | |
446 | p => "D3EF0028FFAB508E2773C659E428A80FB0E9211346B4...", #p factor of N | |
447 | q => "FC07E46B163CAB6A83B8E467D169534B2077DCDEECAE...", #q factor of N | |
448 | qP => "88C6D406F833DF73C8B734548E0385261AD51F4187CF...", #1/q mod p CRT param | |
449 | dP => "486F142FEF0A1F53269AC43D2EE4D263E2841B60DA36...", #d mod (p - 1) CRT param | |
450 | dQ => "4597284B2968B72C4212DB7E8F24360B987B80514DA9...", #d mod (q - 1) CRT param | |
451 | } |
2 | 2 | use strict; |
3 | 3 | use warnings ; |
4 | 4 | |
5 | our $VERSION = '0.014'; | |
6 | $VERSION = eval $VERSION; | |
5 | our $VERSION = '0.013_1'; | |
7 | 6 | |
8 | 7 | require XSLoader; |
9 | 8 | XSLoader::load('CryptX', $VERSION); |
3 | 3 | |
4 | 4 | #undef LTC_SOURCE |
5 | 5 | #include "tomcrypt.h" |
6 | #include "tommath.h" | |
6 | 7 | |
7 | 8 | typedef struct cipher_struct { /* used by Crypt::Cipher */ |
8 | 9 | symmetric_key skey; |
60 | 60 | OUTPUT: |
61 | 61 | RETVAL |
62 | 62 | |
63 | int | |
64 | size_q(Crypt::PK::DSA self) | |
65 | CODE: | |
66 | if (self->key.type == -1 || self->key.qord <= 0) XSRETURN_UNDEF; | |
67 | RETVAL = ltc_mp.unsigned_size(self->key.q); | |
68 | OUTPUT: | |
69 | RETVAL | |
70 | ||
71 | SV* | |
72 | key2hash(Crypt::PK::DSA self) | |
73 | INIT: | |
74 | HV *rv_hash; | |
75 | unsigned char buf[20001]; | |
76 | CODE: | |
77 | if (self->key.type == -1 || self->key.qord <= 0) XSRETURN_UNDEF; | |
78 | rv_hash = newHV(); | |
79 | /* =====> g */ | |
80 | if (ltc_mp.unsigned_size(self->key.g)>10000) { | |
81 | croak("FATAL: key2hash failed - 'g' too big number"); | |
82 | } | |
83 | if (ltc_mp.unsigned_size(self->key.g)>0) { | |
84 | mp_tohex(self->key.g, buf); | |
85 | hv_store(rv_hash, "g", 1, newSVpv(buf, strlen(buf)), 0); | |
86 | } | |
87 | else{ | |
88 | hv_store(rv_hash, "g", 1, newSVpv("", 0), 0); | |
89 | } | |
90 | /* =====> q */ | |
91 | if (ltc_mp.unsigned_size(self->key.q)>10000) { | |
92 | croak("FATAL: key2hash failed - 'q' too big number"); | |
93 | } | |
94 | if (ltc_mp.unsigned_size(self->key.q)>0) { | |
95 | mp_tohex(self->key.q, buf); | |
96 | hv_store(rv_hash, "q", 1, newSVpv(buf, strlen(buf)), 0); | |
97 | } | |
98 | else{ | |
99 | hv_store(rv_hash, "q", 1, newSVpv("", 0), 0); | |
100 | } | |
101 | /* =====> p */ | |
102 | if (ltc_mp.unsigned_size(self->key.p)>10000) { | |
103 | croak("FATAL: key2hash failed - 'p' too big number"); | |
104 | } | |
105 | if (ltc_mp.unsigned_size(self->key.p)>0) { | |
106 | mp_tohex(self->key.p, buf); | |
107 | hv_store(rv_hash, "p", 1, newSVpv(buf, strlen(buf)), 0); | |
108 | } | |
109 | else{ | |
110 | hv_store(rv_hash, "p", 1, newSVpv("", 0), 0); | |
111 | } | |
112 | /* =====> x */ | |
113 | if (ltc_mp.unsigned_size(self->key.x)>10000) { | |
114 | croak("FATAL: key2hash failed - 'x' too big number"); | |
115 | } | |
116 | if (ltc_mp.unsigned_size(self->key.x)>0) { | |
117 | mp_tohex(self->key.x, buf); | |
118 | hv_store(rv_hash, "x", 1, newSVpv(buf, strlen(buf)), 0); | |
119 | } | |
120 | else{ | |
121 | hv_store(rv_hash, "x", 1, newSVpv("", 0), 0); | |
122 | } | |
123 | /* =====> y */ | |
124 | if (ltc_mp.unsigned_size(self->key.y)>10000) { | |
125 | croak("FATAL: key2hash failed - 'y' too big number"); | |
126 | } | |
127 | if (ltc_mp.unsigned_size(self->key.y)>0) { | |
128 | mp_tohex(self->key.y, buf); | |
129 | hv_store(rv_hash, "y", 1, newSVpv(buf, strlen(buf)), 0); | |
130 | } | |
131 | else{ | |
132 | hv_store(rv_hash, "y", 1, newSVpv("", 0), 0); | |
133 | } | |
134 | /* =====> qord */ | |
135 | hv_store(rv_hash, "qord", 4, newSViv(self->key.qord), 0); | |
136 | /* =====> type */ | |
137 | hv_store(rv_hash, "type", 4, newSViv(self->key.type), 0); | |
138 | RETVAL = newRV_noinc((SV*)rv_hash); | |
139 | OUTPUT: | |
140 | RETVAL | |
141 | ||
63 | 142 | SV * |
64 | 143 | export_key_der(Crypt::PK::DSA self, char * type) |
65 | 144 | CODE: |
58 | 58 | CODE: |
59 | 59 | if (self->key.type == -1 || self->key.N == NULL) XSRETURN_UNDEF; |
60 | 60 | RETVAL = ltc_mp.unsigned_size(self->key.N); |
61 | OUTPUT: | |
62 | RETVAL | |
63 | ||
64 | SV* | |
65 | key2hash(Crypt::PK::RSA self) | |
66 | INIT: | |
67 | HV *rv_hash; | |
68 | unsigned char buf[20001]; | |
69 | CODE: | |
70 | if (self->key.type == -1 || self->key.N == NULL) XSRETURN_UNDEF; | |
71 | rv_hash = newHV(); | |
72 | /* =====> e */ | |
73 | if (ltc_mp.unsigned_size(self->key.e)>10000) { | |
74 | croak("FATAL: key2hash failed - 'e' too big number"); | |
75 | } | |
76 | if (ltc_mp.unsigned_size(self->key.e)>0) { | |
77 | mp_tohex(self->key.e, buf); | |
78 | hv_store(rv_hash, "e", 1, newSVpv(buf, strlen(buf)), 0); | |
79 | } | |
80 | else{ | |
81 | hv_store(rv_hash, "e", 1, newSVpv("", 0), 0); | |
82 | } | |
83 | /* =====> d */ | |
84 | if (ltc_mp.unsigned_size(self->key.d)>10000) { | |
85 | croak("FATAL: key2hash failed - 'd' too big number"); | |
86 | } | |
87 | if (ltc_mp.unsigned_size(self->key.d)>0) { | |
88 | mp_tohex(self->key.d, buf); | |
89 | hv_store(rv_hash, "d", 1, newSVpv(buf, strlen(buf)), 0); | |
90 | } | |
91 | else{ | |
92 | hv_store(rv_hash, "d", 1, newSVpv("", 0), 0); | |
93 | } | |
94 | /* =====> N */ | |
95 | if (ltc_mp.unsigned_size(self->key.N)>10000) { | |
96 | croak("FATAL: key2hash failed - 'N' too big number"); | |
97 | } | |
98 | if (ltc_mp.unsigned_size(self->key.N)>0) { | |
99 | mp_tohex(self->key.N, buf); | |
100 | hv_store(rv_hash, "N", 1, newSVpv(buf, strlen(buf)), 0); | |
101 | } | |
102 | else{ | |
103 | hv_store(rv_hash, "N", 1, newSVpv("", 0), 0); | |
104 | } | |
105 | /* =====> q */ | |
106 | if (ltc_mp.unsigned_size(self->key.q)>10000) { | |
107 | croak("FATAL: key2hash failed - 'q' too big number"); | |
108 | } | |
109 | if (ltc_mp.unsigned_size(self->key.q)>0) { | |
110 | mp_tohex(self->key.q, buf); | |
111 | hv_store(rv_hash, "q", 1, newSVpv(buf, strlen(buf)), 0); | |
112 | } | |
113 | else{ | |
114 | hv_store(rv_hash, "q", 1, newSVpv("", 0), 0); | |
115 | } | |
116 | /* =====> p */ | |
117 | if (ltc_mp.unsigned_size(self->key.p)>10000) { | |
118 | croak("FATAL: key2hash failed - 'p' too big number"); | |
119 | } | |
120 | if (ltc_mp.unsigned_size(self->key.p)>0) { | |
121 | mp_tohex(self->key.p, buf); | |
122 | hv_store(rv_hash, "p", 1, newSVpv(buf, strlen(buf)), 0); | |
123 | } | |
124 | else{ | |
125 | hv_store(rv_hash, "p", 1, newSVpv("", 0), 0); | |
126 | } | |
127 | /* =====> qP */ | |
128 | if (ltc_mp.unsigned_size(self->key.qP)>10000) { | |
129 | croak("FATAL: key2hash failed - 'qP' too big number"); | |
130 | } | |
131 | if (ltc_mp.unsigned_size(self->key.qP)>0) { | |
132 | mp_tohex(self->key.qP, buf); | |
133 | hv_store(rv_hash, "qP", 2, newSVpv(buf, strlen(buf)), 0); | |
134 | } | |
135 | else{ | |
136 | hv_store(rv_hash, "qP", 2, newSVpv("", 0), 0); | |
137 | } | |
138 | /* =====> dP */ | |
139 | if (ltc_mp.unsigned_size(self->key.dP)>10000) { | |
140 | croak("FATAL: key2hash failed - 'dP' too big number"); | |
141 | } | |
142 | if (ltc_mp.unsigned_size(self->key.dP)>0) { | |
143 | mp_tohex(self->key.dP, buf); | |
144 | hv_store(rv_hash, "dP", 2, newSVpv(buf, strlen(buf)), 0); | |
145 | } | |
146 | else{ | |
147 | hv_store(rv_hash, "dP", 2, newSVpv("", 0), 0); | |
148 | } | |
149 | /* =====> dQ */ | |
150 | if (ltc_mp.unsigned_size(self->key.dQ)>10000) { | |
151 | croak("FATAL: key2hash failed - 'dQ' too big number"); | |
152 | } | |
153 | if (ltc_mp.unsigned_size(self->key.dQ)>0) { | |
154 | mp_tohex(self->key.dQ, buf); | |
155 | hv_store(rv_hash, "dQ", 2, newSVpv(buf, strlen(buf)), 0); | |
156 | } | |
157 | else{ | |
158 | hv_store(rv_hash, "dQ", 2, newSVpv("", 0), 0); | |
159 | } | |
160 | /* =====> type */ | |
161 | hv_store(rv_hash, "type", 4, newSViv(self->key.type), 0); | |
162 | RETVAL = newRV_noinc((SV*)rv_hash); | |
61 | 163 | OUTPUT: |
62 | 164 | RETVAL |
63 | 165 |
1 | 1 | use warnings; |
2 | 2 | use Test::More; |
3 | 3 | |
4 | use Crypt::PK::DSA qw(dsa_encrypt dsa_decrypt dsa_sign dsa_verify); | |
4 | use Crypt::PK::DSA qw(dsa_encrypt dsa_decrypt dsa_sign_message dsa_verify_message); | |
5 | 5 | |
6 | 6 | { |
7 | 7 | my $k; |
67 | 67 | ok(length $ct > 200, 'encrypt ' . length($ct)); |
68 | 68 | is($pt, "secret message", 'decrypt'); |
69 | 69 | |
70 | my $sig = $pr1->sign("message"); | |
70 | my $sig = $pr1->sign_message("message"); | |
71 | 71 | ok(length $sig > 60, 'sign ' . length($sig)); |
72 | ok($pu1->verify($sig, "message"), 'verify'); | |
72 | ok($pu1->verify_message($sig, "message"), 'verify'); | |
73 | 73 | |
74 | 74 | my $pr2 = Crypt::PK::DSA->new; |
75 | 75 | $pr2->import_key('t/data/cryptx_priv_dsa2.der'); |
97 | 97 | ok($ct, 'dsa_encrypt'); |
98 | 98 | my $pt = dsa_decrypt('t/data/cryptx_priv_dsa1.der', $ct); |
99 | 99 | ok($pt, 'dsa_decrypt'); |
100 | my $sig = dsa_sign('t/data/cryptx_priv_dsa1.der', 'test string'); | |
101 | ok($sig, 'dsa_sign'); | |
102 | ok(dsa_verify('t/data/cryptx_pub_dsa1.der', $sig, 'test string'), 'dsa_verify'); | |
100 | my $sig = dsa_sign_message('t/data/cryptx_priv_dsa1.der', 'test string'); | |
101 | ok($sig, 'dsa_sign_message'); | |
102 | ok(dsa_verify_message('t/data/cryptx_pub_dsa1.der', $sig, 'test string'), 'dsa_verify_message'); | |
103 | 103 | } |
104 | 104 | |
105 | 105 | done_testing;⏎ |