New upstream version 0.067
gregor herrmann
4 years ago
0 | 0 | Changes for CryptX |
1 | ||
2 | 0.067 2020-02-01 | |
3 | - new: Crypt::PK::Ed25519 | |
4 | - new: Crypt::PK::X25519 | |
5 | - bundled libtomcrypt update branch:develop (commit:1937f412 2019-11-22) | |
1 | 6 | |
2 | 7 | 0.066 2019-10-20 |
3 | 8 | - fix #57 Build fails on i686 |
146 | 146 | int pindex; |
147 | 147 | ecc_key key; |
148 | 148 | } *Crypt__PK__ECC; |
149 | ||
150 | typedef struct ed25519_struct { /* used by Crypt::PK::Ed25519 */ | |
151 | prng_state pstate; | |
152 | int pindex; | |
153 | curve25519_key key; | |
154 | int initialized; | |
155 | } *Crypt__PK__Ed25519; | |
156 | ||
157 | typedef struct x25519_struct { /* used by Crypt::PK::X25519 */ | |
158 | prng_state pstate; | |
159 | int pindex; | |
160 | curve25519_key key; | |
161 | int initialized; | |
162 | } *Crypt__PK__X25519; | |
149 | 163 | |
150 | 164 | int mp_tohex_with_leading_zero(mp_int * a, char *str, int maxlen, int minlen) { |
151 | 165 | int len, rv; |
746 | 760 | INCLUDE: inc/CryptX_PK_DSA.xs.inc |
747 | 761 | INCLUDE: inc/CryptX_PK_DH.xs.inc |
748 | 762 | INCLUDE: inc/CryptX_PK_ECC.xs.inc |
763 | INCLUDE: inc/CryptX_PK_Ed25519.xs.inc | |
764 | INCLUDE: inc/CryptX_PK_X25519.xs.inc | |
749 | 765 | |
750 | 766 | INCLUDE: inc/CryptX_KeyDerivation.xs.inc |
751 | 767 |
28 | 28 | inc/CryptX_PK_DH.xs.inc |
29 | 29 | inc/CryptX_PK_DSA.xs.inc |
30 | 30 | inc/CryptX_PK_ECC.xs.inc |
31 | inc/CryptX_PK_Ed25519.xs.inc | |
31 | 32 | inc/CryptX_PK_RSA.xs.inc |
33 | inc/CryptX_PK_X25519.xs.inc | |
32 | 34 | inc/CryptX_PRNG.xs.inc |
33 | 35 | inc/CryptX_Stream_ChaCha.xs.inc |
34 | 36 | inc/CryptX_Stream_Rabbit.xs.inc |
128 | 130 | lib/Crypt/PK/DH.pm |
129 | 131 | lib/Crypt/PK/DSA.pm |
130 | 132 | lib/Crypt/PK/ECC.pm |
133 | lib/Crypt/PK/Ed25519.pm | |
131 | 134 | lib/Crypt/PK/RSA.pm |
135 | lib/Crypt/PK/X25519.pm | |
132 | 136 | lib/Crypt/PRNG.pm |
133 | 137 | lib/Crypt/PRNG/ChaCha20.pm |
134 | 138 | lib/Crypt/PRNG/Fortuna.pm |
529 | 533 | src/ltc/pk/ed25519/ed25519_export.c |
530 | 534 | src/ltc/pk/ed25519/ed25519_import.c |
531 | 535 | src/ltc/pk/ed25519/ed25519_import_pkcs8.c |
536 | src/ltc/pk/ed25519/ed25519_import_raw.c | |
532 | 537 | src/ltc/pk/ed25519/ed25519_import_x509.c |
533 | 538 | src/ltc/pk/ed25519/ed25519_make_key.c |
534 | src/ltc/pk/ed25519/ed25519_set_key.c | |
535 | 539 | src/ltc/pk/ed25519/ed25519_sign.c |
536 | 540 | src/ltc/pk/ed25519/ed25519_verify.c |
537 | 541 | src/ltc/pk/pkcs1/pkcs_1_i2osp.c |
560 | 564 | src/ltc/pk/x25519/x25519_export.c |
561 | 565 | src/ltc/pk/x25519/x25519_import.c |
562 | 566 | src/ltc/pk/x25519/x25519_import_pkcs8.c |
567 | src/ltc/pk/x25519/x25519_import_raw.c | |
563 | 568 | src/ltc/pk/x25519/x25519_import_x509.c |
564 | 569 | src/ltc/pk/x25519/x25519_make_key.c |
565 | src/ltc/pk/x25519/x25519_set_key.c | |
566 | 570 | src/ltc/pk/x25519/x25519_shared_secret.c |
567 | 571 | src/ltc/prngs/chacha20.c |
568 | 572 | src/ltc/prngs/fortuna.c |
850 | 854 | t/data/ec-des.pem |
851 | 855 | t/data/ec-des3.pem |
852 | 856 | t/data/ec-seed.pem |
857 | t/data/info.txt | |
853 | 858 | t/data/jwk_ec-priv1.json |
854 | 859 | t/data/jwk_ec-pub.json |
855 | 860 | t/data/jwk_ec-pub1.json |
861 | t/data/jwk_ed25519-priv1.json | |
862 | t/data/jwk_ed25519-pub1.json | |
856 | 863 | t/data/jwk_rsa-priv.json |
857 | 864 | t/data/jwk_rsa-priv1.json |
858 | 865 | t/data/jwk_rsa-pub1.json |
866 | t/data/jwk_x25519-priv1.json | |
867 | t/data/jwk_x25519-pub1.json | |
859 | 868 | t/data/openssl_dsa1.der |
860 | 869 | t/data/openssl_dsa1.pem |
861 | 870 | t/data/openssl_dsa2.der |
873 | 882 | t/data/openssl_ec1.pub.pem |
874 | 883 | t/data/openssl_ec1.pubc.der |
875 | 884 | t/data/openssl_ec1.pubc.pem |
885 | t/data/openssl_ed25519_pk.der | |
886 | t/data/openssl_ed25519_pk.pem | |
887 | t/data/openssl_ed25519_sk.der | |
888 | t/data/openssl_ed25519_sk.pem | |
889 | t/data/openssl_ed25519_sk.pkcs8 | |
890 | t/data/openssl_ed25519_sk_pbes1.pkcs8 | |
891 | t/data/openssl_ed25519_sk_pbes2.pkcs8 | |
892 | t/data/openssl_ed25519_sk_pw.pem | |
893 | t/data/openssl_ed25519_sk_pw_t.pem | |
894 | t/data/openssl_ed25519_sk_t.pem | |
895 | t/data/openssl_ed25519_x509.der | |
896 | t/data/openssl_ed25519_x509.pem | |
876 | 897 | t/data/openssl_rsa-x509.der |
877 | 898 | t/data/openssl_rsa-x509.pem |
878 | 899 | t/data/openssl_rsa1.der |
883 | 904 | t/data/openssl_rsa2.pem |
884 | 905 | t/data/openssl_rsa2.pubonly.der |
885 | 906 | t/data/openssl_rsa2.pubonly.pem |
907 | t/data/openssl_x25519_pk.der | |
908 | t/data/openssl_x25519_pk.pem | |
909 | t/data/openssl_x25519_sk.der | |
910 | t/data/openssl_x25519_sk.pem | |
911 | t/data/openssl_x25519_sk.pkcs8 | |
912 | t/data/openssl_x25519_sk_pbes1.pkcs8 | |
913 | t/data/openssl_x25519_sk_pbes2.pkcs8 | |
914 | t/data/openssl_x25519_sk_pw.pem | |
915 | t/data/openssl_x25519_sk_pw_t.pem | |
916 | t/data/openssl_x25519_sk_t.pem | |
886 | 917 | t/data/pkcs8.ec-priv-nopass.der |
887 | 918 | t/data/pkcs8.ec-priv-nopass.pem |
888 | 919 | t/data/pkcs8.ec-priv-pass.der |
920 | 951 | t/data/ssh/ssh_ecdsa_521.pub |
921 | 952 | t/data/ssh/ssh_ecdsa_521.pub.pkcs8 |
922 | 953 | t/data/ssh/ssh_ecdsa_521.pub.rfc4716 |
954 | t/data/ssh/ssh_ed25519.priv | |
955 | t/data/ssh/ssh_ed25519.pub | |
956 | t/data/ssh/ssh_ed25519.pub.rfc4716 | |
957 | t/data/ssh/ssh_ed25519_pw.priv | |
923 | 958 | t/data/ssh/ssh_rsa_1024 |
924 | 959 | t/data/ssh/ssh_rsa_1024.pub |
925 | 960 | t/data/ssh/ssh_rsa_1024.pub.pem |
1030 | 1065 | t/pk_dsa_test_vectors_openssl.t |
1031 | 1066 | t/pk_ecc.t |
1032 | 1067 | t/pk_ecc_test_vectors_openssl.t |
1068 | t/pk_ed25519.t | |
1033 | 1069 | t/pk_enc_pem.t |
1034 | 1070 | t/pk_rsa.t |
1035 | 1071 | t/pk_rsa_test_vectors_openssl.t |
1072 | t/pk_x25519.t | |
1036 | 1073 | t/pkcs8.t |
1037 | 1074 | t/prng.t |
1038 | 1075 | t/prng_chacha20.t |
0 | 0 | { |
1 | "abstract" : "Crypto toolkit", | |
1 | "abstract" : "Cryptographic toolkit", | |
2 | 2 | "author" : [ |
3 | 3 | "Karel Miko" |
4 | 4 | ], |
44 | 44 | "url" : "https://github.com/DCIT/perl-CryptX" |
45 | 45 | } |
46 | 46 | }, |
47 | "version" : "0.066", | |
47 | "version" : "0.067", | |
48 | 48 | "x_serialization_backend" : "JSON::PP version 2.94" |
49 | 49 | } |
0 | 0 | --- |
1 | abstract: 'Crypto toolkit' | |
1 | abstract: 'Cryptographic toolkit' | |
2 | 2 | author: |
3 | 3 | - 'Karel Miko' |
4 | 4 | build_requires: |
21 | 21 | resources: |
22 | 22 | bugtracker: https://github.com/DCIT/perl-CryptX/issues |
23 | 23 | repository: https://github.com/DCIT/perl-CryptX |
24 | version: '0.066' | |
24 | version: '0.067' | |
25 | 25 | x_serialization_backend: 'CPAN::Meta::YAML version 0.018' |
65 | 65 | NAME => 'CryptX', |
66 | 66 | VERSION_FROM => 'lib/CryptX.pm', |
67 | 67 | AUTHOR => 'Karel Miko', |
68 | ABSTRACT => 'Crypto toolkit', | |
68 | ABSTRACT => 'Cryptographic toolkit', | |
69 | 69 | MIN_PERL_VERSION => '5.006', |
70 | 70 | LICENSE => 'perl_5', |
71 | 71 | META_MERGE => { resources => { repository => 'https://github.com/DCIT/perl-CryptX', bugtracker => 'https://github.com/DCIT/perl-CryptX/issues' } }, |
0 | 0 | # NAME |
1 | 1 | |
2 | CryptX - Cryptographic toolkit (self-contained, no external libraries needed) | |
2 | CryptX - Cryptographic toolkit | |
3 | 3 | |
4 | 4 | # DESCRIPTION |
5 | 5 | |
6 | Cryptography in CryptX is based on [https://github.com/libtom/libtomcrypt](https://github.com/libtom/libtomcrypt) | |
7 | ||
8 | Available modules: | |
6 | Perl modules providing a cryptography based on [LibTomCrypt](https://github.com/libtom/libtomcrypt) library. | |
9 | 7 | |
10 | 8 | - Symmetric ciphers - see [Crypt::Cipher](https://metacpan.org/pod/Crypt::Cipher) and related modules |
11 | 9 | |
49 | 47 | |
50 | 48 | - Public key cryptography |
51 | 49 | |
52 | [Crypt::PK::RSA](https://metacpan.org/pod/Crypt::PK::RSA), [Crypt::PK::DSA](https://metacpan.org/pod/Crypt::PK::DSA), [Crypt::PK::ECC](https://metacpan.org/pod/Crypt::PK::ECC), [Crypt::PK::DH](https://metacpan.org/pod/Crypt::PK::DH) | |
50 | [Crypt::PK::RSA](https://metacpan.org/pod/Crypt::PK::RSA), [Crypt::PK::DSA](https://metacpan.org/pod/Crypt::PK::DSA), [Crypt::PK::ECC](https://metacpan.org/pod/Crypt::PK::ECC), [Crypt::PK::DH](https://metacpan.org/pod/Crypt::PK::DH), [Crypt::PK::Ed25519](https://metacpan.org/pod/Crypt::PK::Ed25519), [Crypt::PK::X25519](https://metacpan.org/pod/Crypt::PK::X25519) | |
53 | 51 | |
54 | 52 | - Cryptographically secure random number generators - see [Crypt::PRNG](https://metacpan.org/pod/Crypt::PRNG) and related modules |
55 | 53 | |
69 | 67 | |
70 | 68 | # COPYRIGHT |
71 | 69 | |
72 | Copyright (c) 2013+ DCIT, a.s. [https://www.dcit.cz](https://www.dcit.cz) / Karel Miko | |
70 | Copyright (c) 2013-2020 DCIT, a.s. [https://www.dcit.cz](https://www.dcit.cz) / Karel Miko |
0 | MODULE = CryptX PACKAGE = Crypt::PK::Ed25519 | |
1 | ||
2 | PROTOTYPES: DISABLE | |
3 | ||
4 | Crypt::PK::Ed25519 | |
5 | _new(Class) | |
6 | CODE: | |
7 | { | |
8 | int rv; | |
9 | Newz(0, RETVAL, 1, struct ed25519_struct); | |
10 | if (!RETVAL) croak("FATAL: Newz failed"); | |
11 | RETVAL->initialized = 0; | |
12 | RETVAL->pindex = find_prng("chacha20"); | |
13 | if (RETVAL->pindex == -1) { | |
14 | Safefree(RETVAL); | |
15 | croak("FATAL: find_prng('chacha20') failed"); | |
16 | } | |
17 | rv = rng_make_prng(320, RETVAL->pindex, &RETVAL->pstate, NULL); /* 320bits = 40bytes */ | |
18 | if (rv != CRYPT_OK) { | |
19 | Safefree(RETVAL); | |
20 | croak("FATAL: rng_make_prng failed: %s", error_to_string(rv)); | |
21 | } | |
22 | } | |
23 | OUTPUT: | |
24 | RETVAL | |
25 | ||
26 | void | |
27 | generate_key(Crypt::PK::Ed25519 self) | |
28 | PPCODE: | |
29 | { | |
30 | int rv; | |
31 | self->initialized = 0; | |
32 | rv = ed25519_make_key(&self->pstate, self->pindex, &self->key); | |
33 | if (rv != CRYPT_OK) croak("FATAL: ed25519_make_key failed: %s", error_to_string(rv)); | |
34 | self->initialized = 1; | |
35 | XPUSHs(ST(0)); /* return self */ | |
36 | } | |
37 | ||
38 | void | |
39 | _import(Crypt::PK::Ed25519 self, SV * key_data) | |
40 | PPCODE: | |
41 | { | |
42 | int rv; | |
43 | unsigned char *data=NULL; | |
44 | STRLEN data_len=0; | |
45 | ||
46 | data = (unsigned char *)SvPVbyte(key_data, data_len); | |
47 | self->initialized = 0; | |
48 | rv = ed25519_import(data, (unsigned long)data_len, &self->key); | |
49 | if (rv != CRYPT_OK) croak("FATAL: ed25519_import failed: %s", error_to_string(rv)); | |
50 | self->initialized = 1; | |
51 | XPUSHs(ST(0)); /* return self */ | |
52 | } | |
53 | ||
54 | void | |
55 | _import_pkcs8(Crypt::PK::Ed25519 self, SV * key_data, SV * passwd) | |
56 | PPCODE: | |
57 | { | |
58 | int rv; | |
59 | unsigned char *data=NULL, *pwd=NULL; | |
60 | STRLEN data_len=0, pwd_len=0; | |
61 | ||
62 | data = (unsigned char *)SvPVbyte(key_data, data_len); | |
63 | if (SvOK(passwd)) { | |
64 | pwd = (unsigned char *)SvPVbyte(passwd, pwd_len); | |
65 | } | |
66 | self->initialized = 0; | |
67 | rv = ed25519_import_pkcs8(data, (unsigned long)data_len, pwd, (unsigned long)pwd_len, &self->key); | |
68 | if (rv != CRYPT_OK) croak("FATAL: ed25519_import_pkcs8 failed: %s", error_to_string(rv)); | |
69 | self->initialized = 1; | |
70 | XPUSHs(ST(0)); /* return self */ | |
71 | } | |
72 | ||
73 | void | |
74 | _import_x509(Crypt::PK::Ed25519 self, SV * key_data) | |
75 | PPCODE: | |
76 | { | |
77 | int rv; | |
78 | unsigned char *data=NULL; | |
79 | STRLEN data_len=0; | |
80 | ||
81 | data = (unsigned char *)SvPVbyte(key_data, data_len); | |
82 | self->initialized = 0; | |
83 | rv = ed25519_import_x509(data, (unsigned long)data_len, &self->key); | |
84 | if (rv != CRYPT_OK) croak("FATAL: ed25519_import_x509 failed: %s", error_to_string(rv)); | |
85 | self->initialized = 1; | |
86 | XPUSHs(ST(0)); /* return self */ | |
87 | } | |
88 | ||
89 | void | |
90 | _import_raw(Crypt::PK::Ed25519 self, SV * key, int which) | |
91 | PPCODE: | |
92 | { | |
93 | int rv; | |
94 | unsigned char *key_data=NULL; | |
95 | STRLEN key_len=0; | |
96 | ||
97 | if (SvOK(key)) { | |
98 | key_data = (unsigned char *)SvPVbyte(key, key_len); | |
99 | } | |
100 | self->initialized = 0; | |
101 | if (which == 0) { | |
102 | rv = ed25519_import_raw(key_data, (unsigned long)key_len, PK_PUBLIC, &self->key); | |
103 | } | |
104 | else if (which == 1) { | |
105 | rv = ed25519_import_raw(key_data, (unsigned long)key_len, PK_PRIVATE, &self->key); | |
106 | } | |
107 | else { | |
108 | croak("FATAL: import_raw invalid type '%d'", which); | |
109 | } | |
110 | if (rv != CRYPT_OK) croak("FATAL: ed25519_import_raw failed: %s", error_to_string(rv)); | |
111 | self->initialized = 1; | |
112 | XPUSHs(ST(0)); /* return self */ | |
113 | } | |
114 | ||
115 | int | |
116 | is_private(Crypt::PK::Ed25519 self) | |
117 | CODE: | |
118 | if (self->initialized == 0) XSRETURN_UNDEF; | |
119 | RETVAL = (self->key.type == PK_PRIVATE) ? 1 : 0; | |
120 | OUTPUT: | |
121 | RETVAL | |
122 | ||
123 | SV* | |
124 | key2hash(Crypt::PK::Ed25519 self) | |
125 | PREINIT: | |
126 | HV *rv_hash; | |
127 | char buf[32 * 2 + 1]; | |
128 | unsigned long blen; | |
129 | SV **not_used; | |
130 | int rv; | |
131 | CODE: | |
132 | if (self->initialized == 0) XSRETURN_UNDEF; | |
133 | rv_hash = newHV(); | |
134 | /* priv */ | |
135 | if (self->key.type == PK_PRIVATE) { | |
136 | blen = sizeof(buf); | |
137 | rv = base16_encode(self->key.priv, sizeof(self->key.priv), buf, &blen, 0); | |
138 | if (rv != CRYPT_OK) croak("FATAL: base16_encode failed: %s", error_to_string(rv)); | |
139 | not_used = hv_store(rv_hash, "priv", 4, newSVpv(buf, blen), 0); | |
140 | } | |
141 | else { | |
142 | not_used = hv_store(rv_hash, "priv", 4, newSVpvn(NULL, 0), 0); /* undef */ | |
143 | } | |
144 | /* pub */ | |
145 | blen = sizeof(buf); | |
146 | rv = base16_encode(self->key.pub, sizeof(self->key.pub), buf, &blen, 0); | |
147 | if (rv != CRYPT_OK) croak("FATAL: base16_encode failed: %s", error_to_string(rv)); | |
148 | not_used = hv_store(rv_hash, "pub", 3, newSVpv(buf, blen), 0); | |
149 | /* curve */ | |
150 | not_used = hv_store(rv_hash, "curve", 5, newSVpv("ed25519", 0), 0); | |
151 | LTC_UNUSED_PARAM(not_used); | |
152 | RETVAL = newRV_noinc((SV*)rv_hash); | |
153 | OUTPUT: | |
154 | RETVAL | |
155 | ||
156 | SV* | |
157 | export_key_der(Crypt::PK::Ed25519 self, char * type) | |
158 | CODE: | |
159 | { | |
160 | int rv; | |
161 | unsigned char out[4096]; | |
162 | unsigned long int out_len = sizeof(out); | |
163 | ||
164 | RETVAL = newSVpvn(NULL, 0); /* undef */ | |
165 | if (strnEQ(type, "private", 7)) { | |
166 | rv = ed25519_export(out, &out_len, PK_PRIVATE|PK_STD, &self->key); | |
167 | if (rv != CRYPT_OK) croak("FATAL: ed25519_export(PK_PRIVATE|PK_STD) failed: %s", error_to_string(rv)); | |
168 | RETVAL = newSVpvn((char*)out, out_len); | |
169 | } | |
170 | else if (strnEQ(type, "public", 6)) { | |
171 | rv = ed25519_export(out, &out_len, PK_PUBLIC|PK_STD, &self->key); | |
172 | if (rv != CRYPT_OK) croak("FATAL: ed25519_export(PK_PUBLIC|PK_STD) failed: %s", error_to_string(rv)); | |
173 | RETVAL = newSVpvn((char*)out, out_len); | |
174 | } | |
175 | else { | |
176 | croak("FATAL: export_key_der invalid type '%s'", type); | |
177 | } | |
178 | } | |
179 | OUTPUT: | |
180 | RETVAL | |
181 | ||
182 | SV* | |
183 | export_key_raw(Crypt::PK::Ed25519 self, char * type) | |
184 | CODE: | |
185 | { | |
186 | int rv; | |
187 | unsigned char out[32]; | |
188 | unsigned long int out_len = sizeof(out); | |
189 | ||
190 | RETVAL = newSVpvn(NULL, 0); /* undef */ | |
191 | if (strnEQ(type, "private", 7)) { | |
192 | rv = ed25519_export(out, &out_len, PK_PRIVATE, &self->key); | |
193 | if (rv != CRYPT_OK) croak("FATAL: ed25519_export(PK_PRIVATE) failed: %s", error_to_string(rv)); | |
194 | RETVAL = newSVpvn((char*)out, out_len); | |
195 | } | |
196 | else if (strnEQ(type, "public", 6)) { | |
197 | rv = ed25519_export(out, &out_len, PK_PUBLIC, &self->key); | |
198 | if (rv != CRYPT_OK) croak("FATAL: ed25519_export(PK_PUBLIC) failed: %s", error_to_string(rv)); | |
199 | RETVAL = newSVpvn((char*)out, out_len); | |
200 | } | |
201 | else { | |
202 | croak("FATAL: export_key_raw invalid type '%s'", type); | |
203 | } | |
204 | } | |
205 | OUTPUT: | |
206 | RETVAL | |
207 | ||
208 | SV * | |
209 | sign_message(Crypt::PK::Ed25519 self, SV * data) | |
210 | CODE: | |
211 | { | |
212 | int rv; | |
213 | unsigned char buffer[64], *data_ptr = NULL; | |
214 | unsigned long buffer_len = 64; | |
215 | STRLEN data_len = 0; | |
216 | ||
217 | data_ptr = (unsigned char *)SvPVbyte(data, data_len); | |
218 | rv = ed25519_sign(data_ptr, (unsigned long)data_len, buffer, &buffer_len, &self->key); | |
219 | if (rv != CRYPT_OK) croak("FATAL: ed25519_sign failed: %s", error_to_string(rv)); | |
220 | RETVAL = newSVpvn((char*)buffer, buffer_len); | |
221 | } | |
222 | OUTPUT: | |
223 | RETVAL | |
224 | ||
225 | int | |
226 | verify_message(Crypt::PK::Ed25519 self, SV * sig, SV * data) | |
227 | CODE: | |
228 | { | |
229 | int rv, stat; | |
230 | unsigned char *data_ptr = NULL, *sig_ptr = NULL; | |
231 | STRLEN data_len = 0, sig_len = 0; | |
232 | ||
233 | data_ptr = (unsigned char *)SvPVbyte(data, data_len); | |
234 | sig_ptr = (unsigned char *)SvPVbyte(sig, sig_len); | |
235 | RETVAL = 0; | |
236 | stat = 0; | |
237 | rv = ed25519_verify(data_ptr, (unsigned long)data_len, sig_ptr, (unsigned long)sig_len, &stat, &self->key); | |
238 | if (rv == CRYPT_OK && stat == 1) RETVAL = 1; | |
239 | } | |
240 | OUTPUT: | |
241 | RETVAL | |
242 | ||
243 | void | |
244 | DESTROY(Crypt::PK::Ed25519 self) | |
245 | CODE: | |
246 | Safefree(self); |
0 | MODULE = CryptX PACKAGE = Crypt::PK::X25519 | |
1 | ||
2 | PROTOTYPES: DISABLE | |
3 | ||
4 | Crypt::PK::X25519 | |
5 | _new(Class) | |
6 | CODE: | |
7 | { | |
8 | int rv; | |
9 | Newz(0, RETVAL, 1, struct x25519_struct); | |
10 | if (!RETVAL) croak("FATAL: Newz failed"); | |
11 | RETVAL->initialized = 0; | |
12 | RETVAL->pindex = find_prng("chacha20"); | |
13 | if (RETVAL->pindex == -1) { | |
14 | Safefree(RETVAL); | |
15 | croak("FATAL: find_prng('chacha20') failed"); | |
16 | } | |
17 | rv = rng_make_prng(320, RETVAL->pindex, &RETVAL->pstate, NULL); /* 320bits = 40bytes */ | |
18 | if (rv != CRYPT_OK) { | |
19 | Safefree(RETVAL); | |
20 | croak("FATAL: rng_make_prng failed: %s", error_to_string(rv)); | |
21 | } | |
22 | } | |
23 | OUTPUT: | |
24 | RETVAL | |
25 | ||
26 | void | |
27 | generate_key(Crypt::PK::X25519 self) | |
28 | PPCODE: | |
29 | { | |
30 | int rv; | |
31 | self->initialized = 0; | |
32 | rv = x25519_make_key(&self->pstate, self->pindex, &self->key); | |
33 | if (rv != CRYPT_OK) croak("FATAL: x25519_make_key failed: %s", error_to_string(rv)); | |
34 | self->initialized = 1; | |
35 | XPUSHs(ST(0)); /* return self */ | |
36 | } | |
37 | ||
38 | void | |
39 | _import(Crypt::PK::X25519 self, SV * key_data) | |
40 | PPCODE: | |
41 | { | |
42 | int rv; | |
43 | unsigned char *data=NULL; | |
44 | STRLEN data_len=0; | |
45 | ||
46 | data = (unsigned char *)SvPVbyte(key_data, data_len); | |
47 | self->initialized = 0; | |
48 | rv = x25519_import(data, (unsigned long)data_len, &self->key); | |
49 | if (rv != CRYPT_OK) croak("FATAL: x25519_import failed: %s", error_to_string(rv)); | |
50 | self->initialized = 1; | |
51 | XPUSHs(ST(0)); /* return self */ | |
52 | } | |
53 | ||
54 | void | |
55 | _import_pkcs8(Crypt::PK::X25519 self, SV * key_data, SV * passwd) | |
56 | PPCODE: | |
57 | { | |
58 | int rv; | |
59 | unsigned char *data=NULL, *pwd=NULL; | |
60 | STRLEN data_len=0, pwd_len=0; | |
61 | ||
62 | data = (unsigned char *)SvPVbyte(key_data, data_len); | |
63 | if (SvOK(passwd)) { | |
64 | pwd = (unsigned char *)SvPVbyte(passwd, pwd_len); | |
65 | } | |
66 | self->initialized = 0; | |
67 | rv = x25519_import_pkcs8(data, (unsigned long)data_len, pwd, (unsigned long)pwd_len, &self->key); | |
68 | if (rv != CRYPT_OK) croak("FATAL: x25519_import_pkcs8 failed: %s", error_to_string(rv)); | |
69 | self->initialized = 1; | |
70 | XPUSHs(ST(0)); /* return self */ | |
71 | } | |
72 | ||
73 | void | |
74 | _import_x509(Crypt::PK::X25519 self, SV * key_data) | |
75 | PPCODE: | |
76 | { | |
77 | int rv; | |
78 | unsigned char *data=NULL; | |
79 | STRLEN data_len=0; | |
80 | ||
81 | data = (unsigned char *)SvPVbyte(key_data, data_len); | |
82 | self->initialized = 0; | |
83 | rv = x25519_import_x509(data, (unsigned long)data_len, &self->key); | |
84 | if (rv != CRYPT_OK) croak("FATAL: x25519_import_x509 failed: %s", error_to_string(rv)); | |
85 | self->initialized = 1; | |
86 | XPUSHs(ST(0)); /* return self */ | |
87 | } | |
88 | ||
89 | void | |
90 | _import_raw(Crypt::PK::X25519 self, SV * key, int which) | |
91 | PPCODE: | |
92 | { | |
93 | int rv; | |
94 | unsigned char *key_data=NULL; | |
95 | STRLEN key_len=0; | |
96 | ||
97 | if (SvOK(key)) { | |
98 | key_data = (unsigned char *)SvPVbyte(key, key_len); | |
99 | } | |
100 | self->initialized = 0; | |
101 | if (which == 0) { | |
102 | rv = x25519_import_raw(key_data, (unsigned long)key_len, PK_PUBLIC, &self->key); | |
103 | } | |
104 | else if (which == 1) { | |
105 | rv = x25519_import_raw(key_data, (unsigned long)key_len, PK_PRIVATE, &self->key); | |
106 | } | |
107 | else { | |
108 | croak("FATAL: import_raw invalid type '%d'", which); | |
109 | } | |
110 | if (rv != CRYPT_OK) croak("FATAL: x25519_import_raw failed: %s", error_to_string(rv)); | |
111 | self->initialized = 1; | |
112 | XPUSHs(ST(0)); /* return self */ | |
113 | } | |
114 | ||
115 | int | |
116 | is_private(Crypt::PK::X25519 self) | |
117 | CODE: | |
118 | if (self->initialized == 0) XSRETURN_UNDEF; | |
119 | RETVAL = (self->key.type == PK_PRIVATE) ? 1 : 0; | |
120 | OUTPUT: | |
121 | RETVAL | |
122 | ||
123 | SV* | |
124 | key2hash(Crypt::PK::X25519 self) | |
125 | PREINIT: | |
126 | HV *rv_hash; | |
127 | char buf[32 * 2 + 1]; | |
128 | unsigned long blen; | |
129 | SV **not_used; | |
130 | int rv; | |
131 | CODE: | |
132 | if (self->initialized == 0) XSRETURN_UNDEF; | |
133 | rv_hash = newHV(); | |
134 | /* priv */ | |
135 | if (self->key.type == PK_PRIVATE) { | |
136 | blen = sizeof(buf); | |
137 | rv = base16_encode(self->key.priv, sizeof(self->key.priv), buf, &blen, 0); | |
138 | if (rv != CRYPT_OK) croak("FATAL: base16_encode failed: %s", error_to_string(rv)); | |
139 | not_used = hv_store(rv_hash, "priv", 4, newSVpv(buf, blen), 0); | |
140 | } | |
141 | else { | |
142 | not_used = hv_store(rv_hash, "priv", 4, newSVpvn(NULL, 0), 0); /* undef */ | |
143 | } | |
144 | /* pub */ | |
145 | blen = sizeof(buf); | |
146 | rv = base16_encode(self->key.pub, sizeof(self->key.pub), buf, &blen, 0); | |
147 | if (rv != CRYPT_OK) croak("FATAL: base16_encode failed: %s", error_to_string(rv)); | |
148 | not_used = hv_store(rv_hash, "pub", 3, newSVpv(buf, blen), 0); | |
149 | /* curve */ | |
150 | not_used = hv_store(rv_hash, "curve", 5, newSVpv("x25519", 0), 0); | |
151 | LTC_UNUSED_PARAM(not_used); | |
152 | RETVAL = newRV_noinc((SV*)rv_hash); | |
153 | OUTPUT: | |
154 | RETVAL | |
155 | ||
156 | SV* | |
157 | export_key_der(Crypt::PK::X25519 self, char * type) | |
158 | CODE: | |
159 | { | |
160 | int rv; | |
161 | unsigned char out[4096]; | |
162 | unsigned long int out_len = sizeof(out); | |
163 | ||
164 | RETVAL = newSVpvn(NULL, 0); /* undef */ | |
165 | if (strnEQ(type, "private", 7)) { | |
166 | rv = x25519_export(out, &out_len, PK_PRIVATE|PK_STD, &self->key); | |
167 | if (rv != CRYPT_OK) croak("FATAL: x25519_export(PK_PRIVATE|PK_STD) failed: %s", error_to_string(rv)); | |
168 | RETVAL = newSVpvn((char*)out, out_len); | |
169 | } | |
170 | else if (strnEQ(type, "public", 6)) { | |
171 | rv = x25519_export(out, &out_len, PK_PUBLIC|PK_STD, &self->key); | |
172 | if (rv != CRYPT_OK) croak("FATAL: x25519_export(PK_PUBLIC|PK_STD) failed: %s", error_to_string(rv)); | |
173 | RETVAL = newSVpvn((char*)out, out_len); | |
174 | } | |
175 | else { | |
176 | croak("FATAL: export_key_der invalid type '%s'", type); | |
177 | } | |
178 | } | |
179 | OUTPUT: | |
180 | RETVAL | |
181 | ||
182 | SV* | |
183 | export_key_raw(Crypt::PK::X25519 self, char * type) | |
184 | CODE: | |
185 | { | |
186 | int rv; | |
187 | unsigned char out[32]; | |
188 | unsigned long int out_len = sizeof(out); | |
189 | ||
190 | RETVAL = newSVpvn(NULL, 0); /* undef */ | |
191 | if (strnEQ(type, "private", 7)) { | |
192 | rv = x25519_export(out, &out_len, PK_PRIVATE, &self->key); | |
193 | if (rv != CRYPT_OK) croak("FATAL: x25519_export(PK_PRIVATE) failed: %s", error_to_string(rv)); | |
194 | RETVAL = newSVpvn((char*)out, out_len); | |
195 | } | |
196 | else if (strnEQ(type, "public", 6)) { | |
197 | rv = x25519_export(out, &out_len, PK_PUBLIC, &self->key); | |
198 | if (rv != CRYPT_OK) croak("FATAL: x25519_export(PK_PUBLIC) failed: %s", error_to_string(rv)); | |
199 | RETVAL = newSVpvn((char*)out, out_len); | |
200 | } | |
201 | else { | |
202 | croak("FATAL: export_key_raw invalid type '%s'", type); | |
203 | } | |
204 | } | |
205 | OUTPUT: | |
206 | RETVAL | |
207 | ||
208 | SV * | |
209 | shared_secret(Crypt::PK::X25519 self, Crypt::PK::X25519 pubkey) | |
210 | CODE: | |
211 | { | |
212 | int rv; | |
213 | unsigned char buffer[1024]; | |
214 | unsigned long int buffer_len = sizeof(buffer); | |
215 | ||
216 | rv = x25519_shared_secret(&self->key, &pubkey->key, buffer, &buffer_len); | |
217 | if (rv != CRYPT_OK) croak("FATAL: x25519_shared_secret failed: %s", error_to_string(rv)); | |
218 | RETVAL = newSVpvn((char*)buffer, buffer_len); | |
219 | } | |
220 | OUTPUT: | |
221 | RETVAL | |
222 | ||
223 | void | |
224 | DESTROY(Crypt::PK::X25519 self) | |
225 | CODE: | |
226 | Safefree(self); |
1 | 1 | |
2 | 2 | use strict; |
3 | 3 | use warnings; |
4 | our $VERSION = '0.066'; | |
4 | our $VERSION = '0.067'; | |
5 | 5 | |
6 | require Exporter; our @ISA = qw(Exporter); ### use Exporter 'import'; | |
6 | require Exporter; our @ISA = qw(Exporter); ### use Exporter 5.57 'import'; | |
7 | 7 | our %EXPORT_TAGS = ( all => [qw( ccm_encrypt_authenticate ccm_decrypt_verify )] ); |
8 | 8 | our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } ); |
9 | 9 | our @EXPORT = qw(); |
1 | 1 | |
2 | 2 | use strict; |
3 | 3 | use warnings; |
4 | our $VERSION = '0.066'; | |
4 | our $VERSION = '0.067'; | |
5 | 5 | |
6 | require Exporter; our @ISA = qw(Exporter); ### use Exporter 'import'; | |
6 | require Exporter; our @ISA = qw(Exporter); ### use Exporter 5.57 'import'; | |
7 | 7 | our %EXPORT_TAGS = ( all => [qw( chacha20poly1305_encrypt_authenticate chacha20poly1305_decrypt_verify )] ); |
8 | 8 | our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } ); |
9 | 9 | our @EXPORT = qw(); |
1 | 1 | |
2 | 2 | use strict; |
3 | 3 | use warnings; |
4 | our $VERSION = '0.066'; | |
4 | our $VERSION = '0.067'; | |
5 | 5 | |
6 | require Exporter; our @ISA = qw(Exporter); ### use Exporter 'import'; | |
6 | require Exporter; our @ISA = qw(Exporter); ### use Exporter 5.57 'import'; | |
7 | 7 | our %EXPORT_TAGS = ( all => [qw( eax_encrypt_authenticate eax_decrypt_verify )] ); |
8 | 8 | our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } ); |
9 | 9 | our @EXPORT = qw(); |
1 | 1 | |
2 | 2 | use strict; |
3 | 3 | use warnings; |
4 | our $VERSION = '0.066'; | |
4 | our $VERSION = '0.067'; | |
5 | 5 | |
6 | require Exporter; our @ISA = qw(Exporter); ### use Exporter 'import'; | |
6 | require Exporter; our @ISA = qw(Exporter); ### use Exporter 5.57 'import'; | |
7 | 7 | our %EXPORT_TAGS = ( all => [qw( gcm_encrypt_authenticate gcm_decrypt_verify )] ); |
8 | 8 | our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } ); |
9 | 9 | our @EXPORT = qw(); |
1 | 1 | |
2 | 2 | use strict; |
3 | 3 | use warnings; |
4 | our $VERSION = '0.066'; | |
4 | our $VERSION = '0.067'; | |
5 | 5 | |
6 | require Exporter; our @ISA = qw(Exporter); ### use Exporter 'import'; | |
6 | require Exporter; our @ISA = qw(Exporter); ### use Exporter 5.57 'import'; | |
7 | 7 | our %EXPORT_TAGS = ( all => [qw( ocb_encrypt_authenticate ocb_decrypt_verify )] ); |
8 | 8 | our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } ); |
9 | 9 | our @EXPORT = qw(); |
1 | 1 | |
2 | 2 | use strict; |
3 | 3 | use warnings; |
4 | our $VERSION = '0.066'; | |
4 | our $VERSION = '0.067'; | |
5 | 5 | |
6 | 6 | ### not used |
7 | 7 |
1 | 1 | |
2 | 2 | use strict; |
3 | 3 | use warnings; |
4 | our $VERSION = '0.066'; | |
4 | our $VERSION = '0.067'; | |
5 | 5 | |
6 | 6 | use base qw(Crypt::Checksum Exporter); |
7 | 7 | our %EXPORT_TAGS = ( all => [qw( adler32_data adler32_data_hex adler32_data_int adler32_file adler32_file_hex adler32_file_int )] ); |
1 | 1 | |
2 | 2 | use strict; |
3 | 3 | use warnings; |
4 | our $VERSION = '0.066'; | |
4 | our $VERSION = '0.067'; | |
5 | 5 | |
6 | 6 | use base qw(Crypt::Checksum Exporter); |
7 | 7 | our %EXPORT_TAGS = ( all => [qw( crc32_data crc32_data_hex crc32_data_int crc32_file crc32_file_hex crc32_file_int )] ); |
1 | 1 | |
2 | 2 | use strict; |
3 | 3 | use warnings; |
4 | our $VERSION = '0.066'; | |
4 | our $VERSION = '0.067'; | |
5 | 5 | |
6 | require Exporter; our @ISA = qw(Exporter); ### use Exporter 'import'; | |
6 | require Exporter; our @ISA = qw(Exporter); ### use Exporter 5.57 'import'; | |
7 | 7 | our %EXPORT_TAGS = ( all => [qw/ adler32_data adler32_data_hex adler32_data_int adler32_file adler32_file_hex adler32_file_int |
8 | 8 | crc32_data crc32_data_hex crc32_data_int crc32_file crc32_file_hex crc32_file_int /] ); |
9 | 9 | our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } ); |
3 | 3 | |
4 | 4 | use strict; |
5 | 5 | use warnings; |
6 | our $VERSION = '0.066'; | |
6 | our $VERSION = '0.067'; | |
7 | 7 | |
8 | 8 | use base qw(Crypt::Cipher); |
9 | 9 |
3 | 3 | |
4 | 4 | use strict; |
5 | 5 | use warnings; |
6 | our $VERSION = '0.066'; | |
6 | our $VERSION = '0.067'; | |
7 | 7 | |
8 | 8 | use base qw(Crypt::Cipher); |
9 | 9 |
3 | 3 | |
4 | 4 | use strict; |
5 | 5 | use warnings; |
6 | our $VERSION = '0.066'; | |
6 | our $VERSION = '0.067'; | |
7 | 7 | |
8 | 8 | use base qw(Crypt::Cipher); |
9 | 9 |
3 | 3 | |
4 | 4 | use strict; |
5 | 5 | use warnings; |
6 | our $VERSION = '0.066'; | |
6 | our $VERSION = '0.067'; | |
7 | 7 | |
8 | 8 | use base qw(Crypt::Cipher); |
9 | 9 |
3 | 3 | |
4 | 4 | use strict; |
5 | 5 | use warnings; |
6 | our $VERSION = '0.066'; | |
6 | our $VERSION = '0.067'; | |
7 | 7 | |
8 | 8 | use base qw(Crypt::Cipher); |
9 | 9 |
3 | 3 | |
4 | 4 | use strict; |
5 | 5 | use warnings; |
6 | our $VERSION = '0.066'; | |
6 | our $VERSION = '0.067'; | |
7 | 7 | |
8 | 8 | use base qw(Crypt::Cipher); |
9 | 9 |
3 | 3 | |
4 | 4 | use strict; |
5 | 5 | use warnings; |
6 | our $VERSION = '0.066'; | |
6 | our $VERSION = '0.067'; | |
7 | 7 | |
8 | 8 | use base qw(Crypt::Cipher); |
9 | 9 |
3 | 3 | |
4 | 4 | use strict; |
5 | 5 | use warnings; |
6 | our $VERSION = '0.066'; | |
6 | our $VERSION = '0.067'; | |
7 | 7 | |
8 | 8 | use base qw(Crypt::Cipher); |
9 | 9 |
3 | 3 | |
4 | 4 | use strict; |
5 | 5 | use warnings; |
6 | our $VERSION = '0.066'; | |
6 | our $VERSION = '0.067'; | |
7 | 7 | |
8 | 8 | use base qw(Crypt::Cipher); |
9 | 9 |
3 | 3 | |
4 | 4 | use strict; |
5 | 5 | use warnings; |
6 | our $VERSION = '0.066'; | |
6 | our $VERSION = '0.067'; | |
7 | 7 | |
8 | 8 | use base qw(Crypt::Cipher); |
9 | 9 |
3 | 3 | |
4 | 4 | use strict; |
5 | 5 | use warnings; |
6 | our $VERSION = '0.066'; | |
6 | our $VERSION = '0.067'; | |
7 | 7 | |
8 | 8 | use base qw(Crypt::Cipher); |
9 | 9 |
3 | 3 | |
4 | 4 | use strict; |
5 | 5 | use warnings; |
6 | our $VERSION = '0.066'; | |
6 | our $VERSION = '0.067'; | |
7 | 7 | |
8 | 8 | use base qw(Crypt::Cipher); |
9 | 9 |
3 | 3 | |
4 | 4 | use strict; |
5 | 5 | use warnings; |
6 | our $VERSION = '0.066'; | |
6 | our $VERSION = '0.067'; | |
7 | 7 | |
8 | 8 | use base qw(Crypt::Cipher); |
9 | 9 |
3 | 3 | |
4 | 4 | use strict; |
5 | 5 | use warnings; |
6 | our $VERSION = '0.066'; | |
6 | our $VERSION = '0.067'; | |
7 | 7 | |
8 | 8 | use base qw(Crypt::Cipher); |
9 | 9 |
3 | 3 | |
4 | 4 | use strict; |
5 | 5 | use warnings; |
6 | our $VERSION = '0.066'; | |
6 | our $VERSION = '0.067'; | |
7 | 7 | |
8 | 8 | use base qw(Crypt::Cipher); |
9 | 9 |
3 | 3 | |
4 | 4 | use strict; |
5 | 5 | use warnings; |
6 | our $VERSION = '0.066'; | |
6 | our $VERSION = '0.067'; | |
7 | 7 | |
8 | 8 | use base qw(Crypt::Cipher); |
9 | 9 |
3 | 3 | |
4 | 4 | use strict; |
5 | 5 | use warnings; |
6 | our $VERSION = '0.066'; | |
6 | our $VERSION = '0.067'; | |
7 | 7 | |
8 | 8 | use base qw(Crypt::Cipher); |
9 | 9 |
3 | 3 | |
4 | 4 | use strict; |
5 | 5 | use warnings; |
6 | our $VERSION = '0.066'; | |
6 | our $VERSION = '0.067'; | |
7 | 7 | |
8 | 8 | use base qw(Crypt::Cipher); |
9 | 9 |
3 | 3 | |
4 | 4 | use strict; |
5 | 5 | use warnings; |
6 | our $VERSION = '0.066'; | |
6 | our $VERSION = '0.067'; | |
7 | 7 | |
8 | 8 | use base qw(Crypt::Cipher); |
9 | 9 |
3 | 3 | |
4 | 4 | use strict; |
5 | 5 | use warnings; |
6 | our $VERSION = '0.066'; | |
6 | our $VERSION = '0.067'; | |
7 | 7 | |
8 | 8 | use base qw(Crypt::Cipher); |
9 | 9 |
3 | 3 | |
4 | 4 | use strict; |
5 | 5 | use warnings; |
6 | our $VERSION = '0.066'; | |
6 | our $VERSION = '0.067'; | |
7 | 7 | |
8 | 8 | use base qw(Crypt::Cipher); |
9 | 9 |
3 | 3 | |
4 | 4 | use strict; |
5 | 5 | use warnings; |
6 | our $VERSION = '0.066'; | |
6 | our $VERSION = '0.067'; | |
7 | 7 | |
8 | 8 | use base qw(Crypt::Cipher); |
9 | 9 |
3 | 3 | |
4 | 4 | use strict; |
5 | 5 | use warnings; |
6 | our $VERSION = '0.066'; | |
6 | our $VERSION = '0.067'; | |
7 | 7 | |
8 | 8 | use base qw(Crypt::Cipher); |
9 | 9 |
3 | 3 | |
4 | 4 | use strict; |
5 | 5 | use warnings; |
6 | our $VERSION = '0.066'; | |
6 | our $VERSION = '0.067'; | |
7 | 7 | |
8 | 8 | use base qw(Crypt::Cipher); |
9 | 9 |
3 | 3 | |
4 | 4 | use strict; |
5 | 5 | use warnings; |
6 | our $VERSION = '0.066'; | |
6 | our $VERSION = '0.067'; | |
7 | 7 | |
8 | 8 | use base qw(Crypt::Cipher); |
9 | 9 |
1 | 1 | |
2 | 2 | use strict; |
3 | 3 | use warnings; |
4 | our $VERSION = '0.066'; | |
4 | our $VERSION = '0.067'; | |
5 | 5 | |
6 | 6 | use Carp; |
7 | 7 | $Carp::Internal{(__PACKAGE__)}++; |
3 | 3 | |
4 | 4 | use strict; |
5 | 5 | use warnings; |
6 | our $VERSION = '0.066'; | |
6 | our $VERSION = '0.067'; | |
7 | 7 | |
8 | 8 | use base qw(Crypt::Digest Exporter); |
9 | 9 | our %EXPORT_TAGS = ( all => [qw( blake2b_160 blake2b_160_hex blake2b_160_b64 blake2b_160_b64u blake2b_160_file blake2b_160_file_hex blake2b_160_file_b64 blake2b_160_file_b64u )] ); |
3 | 3 | |
4 | 4 | use strict; |
5 | 5 | use warnings; |
6 | our $VERSION = '0.066'; | |
6 | our $VERSION = '0.067'; | |
7 | 7 | |
8 | 8 | use base qw(Crypt::Digest Exporter); |
9 | 9 | our %EXPORT_TAGS = ( all => [qw( blake2b_256 blake2b_256_hex blake2b_256_b64 blake2b_256_b64u blake2b_256_file blake2b_256_file_hex blake2b_256_file_b64 blake2b_256_file_b64u )] ); |
3 | 3 | |
4 | 4 | use strict; |
5 | 5 | use warnings; |
6 | our $VERSION = '0.066'; | |
6 | our $VERSION = '0.067'; | |
7 | 7 | |
8 | 8 | use base qw(Crypt::Digest Exporter); |
9 | 9 | our %EXPORT_TAGS = ( all => [qw( blake2b_384 blake2b_384_hex blake2b_384_b64 blake2b_384_b64u blake2b_384_file blake2b_384_file_hex blake2b_384_file_b64 blake2b_384_file_b64u )] ); |
3 | 3 | |
4 | 4 | use strict; |
5 | 5 | use warnings; |
6 | our $VERSION = '0.066'; | |
6 | our $VERSION = '0.067'; | |
7 | 7 | |
8 | 8 | use base qw(Crypt::Digest Exporter); |
9 | 9 | our %EXPORT_TAGS = ( all => [qw( blake2b_512 blake2b_512_hex blake2b_512_b64 blake2b_512_b64u blake2b_512_file blake2b_512_file_hex blake2b_512_file_b64 blake2b_512_file_b64u )] ); |
3 | 3 | |
4 | 4 | use strict; |
5 | 5 | use warnings; |
6 | our $VERSION = '0.066'; | |
6 | our $VERSION = '0.067'; | |
7 | 7 | |
8 | 8 | use base qw(Crypt::Digest Exporter); |
9 | 9 | our %EXPORT_TAGS = ( all => [qw( blake2s_128 blake2s_128_hex blake2s_128_b64 blake2s_128_b64u blake2s_128_file blake2s_128_file_hex blake2s_128_file_b64 blake2s_128_file_b64u )] ); |
3 | 3 | |
4 | 4 | use strict; |
5 | 5 | use warnings; |
6 | our $VERSION = '0.066'; | |
6 | our $VERSION = '0.067'; | |
7 | 7 | |
8 | 8 | use base qw(Crypt::Digest Exporter); |
9 | 9 | our %EXPORT_TAGS = ( all => [qw( blake2s_160 blake2s_160_hex blake2s_160_b64 blake2s_160_b64u blake2s_160_file blake2s_160_file_hex blake2s_160_file_b64 blake2s_160_file_b64u )] ); |
3 | 3 | |
4 | 4 | use strict; |
5 | 5 | use warnings; |
6 | our $VERSION = '0.066'; | |
6 | our $VERSION = '0.067'; | |
7 | 7 | |
8 | 8 | use base qw(Crypt::Digest Exporter); |
9 | 9 | our %EXPORT_TAGS = ( all => [qw( blake2s_224 blake2s_224_hex blake2s_224_b64 blake2s_224_b64u blake2s_224_file blake2s_224_file_hex blake2s_224_file_b64 blake2s_224_file_b64u )] ); |
3 | 3 | |
4 | 4 | use strict; |
5 | 5 | use warnings; |
6 | our $VERSION = '0.066'; | |
6 | our $VERSION = '0.067'; | |
7 | 7 | |
8 | 8 | use base qw(Crypt::Digest Exporter); |
9 | 9 | our %EXPORT_TAGS = ( all => [qw( blake2s_256 blake2s_256_hex blake2s_256_b64 blake2s_256_b64u blake2s_256_file blake2s_256_file_hex blake2s_256_file_b64 blake2s_256_file_b64u )] ); |
3 | 3 | |
4 | 4 | use strict; |
5 | 5 | use warnings; |
6 | our $VERSION = '0.066'; | |
6 | our $VERSION = '0.067'; | |
7 | 7 | |
8 | 8 | use base qw(Crypt::Digest Exporter); |
9 | 9 | our %EXPORT_TAGS = ( all => [qw( chaes chaes_hex chaes_b64 chaes_b64u chaes_file chaes_file_hex chaes_file_b64 chaes_file_b64u )] ); |
3 | 3 | |
4 | 4 | use strict; |
5 | 5 | use warnings; |
6 | our $VERSION = '0.066'; | |
6 | our $VERSION = '0.067'; | |
7 | 7 | |
8 | 8 | use base qw(Crypt::Digest Exporter); |
9 | 9 | our %EXPORT_TAGS = ( all => [qw( keccak224 keccak224_hex keccak224_b64 keccak224_b64u keccak224_file keccak224_file_hex keccak224_file_b64 keccak224_file_b64u )] ); |
3 | 3 | |
4 | 4 | use strict; |
5 | 5 | use warnings; |
6 | our $VERSION = '0.066'; | |
6 | our $VERSION = '0.067'; | |
7 | 7 | |
8 | 8 | use base qw(Crypt::Digest Exporter); |
9 | 9 | our %EXPORT_TAGS = ( all => [qw( keccak256 keccak256_hex keccak256_b64 keccak256_b64u keccak256_file keccak256_file_hex keccak256_file_b64 keccak256_file_b64u )] ); |
3 | 3 | |
4 | 4 | use strict; |
5 | 5 | use warnings; |
6 | our $VERSION = '0.066'; | |
6 | our $VERSION = '0.067'; | |
7 | 7 | |
8 | 8 | use base qw(Crypt::Digest Exporter); |
9 | 9 | our %EXPORT_TAGS = ( all => [qw( keccak384 keccak384_hex keccak384_b64 keccak384_b64u keccak384_file keccak384_file_hex keccak384_file_b64 keccak384_file_b64u )] ); |
3 | 3 | |
4 | 4 | use strict; |
5 | 5 | use warnings; |
6 | our $VERSION = '0.066'; | |
6 | our $VERSION = '0.067'; | |
7 | 7 | |
8 | 8 | use base qw(Crypt::Digest Exporter); |
9 | 9 | our %EXPORT_TAGS = ( all => [qw( keccak512 keccak512_hex keccak512_b64 keccak512_b64u keccak512_file keccak512_file_hex keccak512_file_b64 keccak512_file_b64u )] ); |
3 | 3 | |
4 | 4 | use strict; |
5 | 5 | use warnings; |
6 | our $VERSION = '0.066'; | |
6 | our $VERSION = '0.067'; | |
7 | 7 | |
8 | 8 | use base qw(Crypt::Digest Exporter); |
9 | 9 | our %EXPORT_TAGS = ( all => [qw( md2 md2_hex md2_b64 md2_b64u md2_file md2_file_hex md2_file_b64 md2_file_b64u )] ); |
3 | 3 | |
4 | 4 | use strict; |
5 | 5 | use warnings; |
6 | our $VERSION = '0.066'; | |
6 | our $VERSION = '0.067'; | |
7 | 7 | |
8 | 8 | use base qw(Crypt::Digest Exporter); |
9 | 9 | our %EXPORT_TAGS = ( all => [qw( md4 md4_hex md4_b64 md4_b64u md4_file md4_file_hex md4_file_b64 md4_file_b64u )] ); |
3 | 3 | |
4 | 4 | use strict; |
5 | 5 | use warnings; |
6 | our $VERSION = '0.066'; | |
6 | our $VERSION = '0.067'; | |
7 | 7 | |
8 | 8 | use base qw(Crypt::Digest Exporter); |
9 | 9 | our %EXPORT_TAGS = ( all => [qw( md5 md5_hex md5_b64 md5_b64u md5_file md5_file_hex md5_file_b64 md5_file_b64u )] ); |
3 | 3 | |
4 | 4 | use strict; |
5 | 5 | use warnings; |
6 | our $VERSION = '0.066'; | |
6 | our $VERSION = '0.067'; | |
7 | 7 | |
8 | 8 | use base qw(Crypt::Digest Exporter); |
9 | 9 | our %EXPORT_TAGS = ( all => [qw( ripemd128 ripemd128_hex ripemd128_b64 ripemd128_b64u ripemd128_file ripemd128_file_hex ripemd128_file_b64 ripemd128_file_b64u )] ); |
3 | 3 | |
4 | 4 | use strict; |
5 | 5 | use warnings; |
6 | our $VERSION = '0.066'; | |
6 | our $VERSION = '0.067'; | |
7 | 7 | |
8 | 8 | use base qw(Crypt::Digest Exporter); |
9 | 9 | our %EXPORT_TAGS = ( all => [qw( ripemd160 ripemd160_hex ripemd160_b64 ripemd160_b64u ripemd160_file ripemd160_file_hex ripemd160_file_b64 ripemd160_file_b64u )] ); |
3 | 3 | |
4 | 4 | use strict; |
5 | 5 | use warnings; |
6 | our $VERSION = '0.066'; | |
6 | our $VERSION = '0.067'; | |
7 | 7 | |
8 | 8 | use base qw(Crypt::Digest Exporter); |
9 | 9 | our %EXPORT_TAGS = ( all => [qw( ripemd256 ripemd256_hex ripemd256_b64 ripemd256_b64u ripemd256_file ripemd256_file_hex ripemd256_file_b64 ripemd256_file_b64u )] ); |
3 | 3 | |
4 | 4 | use strict; |
5 | 5 | use warnings; |
6 | our $VERSION = '0.066'; | |
6 | our $VERSION = '0.067'; | |
7 | 7 | |
8 | 8 | use base qw(Crypt::Digest Exporter); |
9 | 9 | our %EXPORT_TAGS = ( all => [qw( ripemd320 ripemd320_hex ripemd320_b64 ripemd320_b64u ripemd320_file ripemd320_file_hex ripemd320_file_b64 ripemd320_file_b64u )] ); |
3 | 3 | |
4 | 4 | use strict; |
5 | 5 | use warnings; |
6 | our $VERSION = '0.066'; | |
6 | our $VERSION = '0.067'; | |
7 | 7 | |
8 | 8 | use base qw(Crypt::Digest Exporter); |
9 | 9 | our %EXPORT_TAGS = ( all => [qw( sha1 sha1_hex sha1_b64 sha1_b64u sha1_file sha1_file_hex sha1_file_b64 sha1_file_b64u )] ); |
3 | 3 | |
4 | 4 | use strict; |
5 | 5 | use warnings; |
6 | our $VERSION = '0.066'; | |
6 | our $VERSION = '0.067'; | |
7 | 7 | |
8 | 8 | use base qw(Crypt::Digest Exporter); |
9 | 9 | our %EXPORT_TAGS = ( all => [qw( sha224 sha224_hex sha224_b64 sha224_b64u sha224_file sha224_file_hex sha224_file_b64 sha224_file_b64u )] ); |
3 | 3 | |
4 | 4 | use strict; |
5 | 5 | use warnings; |
6 | our $VERSION = '0.066'; | |
6 | our $VERSION = '0.067'; | |
7 | 7 | |
8 | 8 | use base qw(Crypt::Digest Exporter); |
9 | 9 | our %EXPORT_TAGS = ( all => [qw( sha256 sha256_hex sha256_b64 sha256_b64u sha256_file sha256_file_hex sha256_file_b64 sha256_file_b64u )] ); |
3 | 3 | |
4 | 4 | use strict; |
5 | 5 | use warnings; |
6 | our $VERSION = '0.066'; | |
6 | our $VERSION = '0.067'; | |
7 | 7 | |
8 | 8 | use base qw(Crypt::Digest Exporter); |
9 | 9 | our %EXPORT_TAGS = ( all => [qw( sha384 sha384_hex sha384_b64 sha384_b64u sha384_file sha384_file_hex sha384_file_b64 sha384_file_b64u )] ); |
3 | 3 | |
4 | 4 | use strict; |
5 | 5 | use warnings; |
6 | our $VERSION = '0.066'; | |
6 | our $VERSION = '0.067'; | |
7 | 7 | |
8 | 8 | use base qw(Crypt::Digest Exporter); |
9 | 9 | our %EXPORT_TAGS = ( all => [qw( sha3_224 sha3_224_hex sha3_224_b64 sha3_224_b64u sha3_224_file sha3_224_file_hex sha3_224_file_b64 sha3_224_file_b64u )] ); |
3 | 3 | |
4 | 4 | use strict; |
5 | 5 | use warnings; |
6 | our $VERSION = '0.066'; | |
6 | our $VERSION = '0.067'; | |
7 | 7 | |
8 | 8 | use base qw(Crypt::Digest Exporter); |
9 | 9 | our %EXPORT_TAGS = ( all => [qw( sha3_256 sha3_256_hex sha3_256_b64 sha3_256_b64u sha3_256_file sha3_256_file_hex sha3_256_file_b64 sha3_256_file_b64u )] ); |
3 | 3 | |
4 | 4 | use strict; |
5 | 5 | use warnings; |
6 | our $VERSION = '0.066'; | |
6 | our $VERSION = '0.067'; | |
7 | 7 | |
8 | 8 | use base qw(Crypt::Digest Exporter); |
9 | 9 | our %EXPORT_TAGS = ( all => [qw( sha3_384 sha3_384_hex sha3_384_b64 sha3_384_b64u sha3_384_file sha3_384_file_hex sha3_384_file_b64 sha3_384_file_b64u )] ); |
3 | 3 | |
4 | 4 | use strict; |
5 | 5 | use warnings; |
6 | our $VERSION = '0.066'; | |
6 | our $VERSION = '0.067'; | |
7 | 7 | |
8 | 8 | use base qw(Crypt::Digest Exporter); |
9 | 9 | our %EXPORT_TAGS = ( all => [qw( sha3_512 sha3_512_hex sha3_512_b64 sha3_512_b64u sha3_512_file sha3_512_file_hex sha3_512_file_b64 sha3_512_file_b64u )] ); |
3 | 3 | |
4 | 4 | use strict; |
5 | 5 | use warnings; |
6 | our $VERSION = '0.066'; | |
6 | our $VERSION = '0.067'; | |
7 | 7 | |
8 | 8 | use base qw(Crypt::Digest Exporter); |
9 | 9 | our %EXPORT_TAGS = ( all => [qw( sha512 sha512_hex sha512_b64 sha512_b64u sha512_file sha512_file_hex sha512_file_b64 sha512_file_b64u )] ); |
3 | 3 | |
4 | 4 | use strict; |
5 | 5 | use warnings; |
6 | our $VERSION = '0.066'; | |
6 | our $VERSION = '0.067'; | |
7 | 7 | |
8 | 8 | use base qw(Crypt::Digest Exporter); |
9 | 9 | our %EXPORT_TAGS = ( all => [qw( sha512_224 sha512_224_hex sha512_224_b64 sha512_224_b64u sha512_224_file sha512_224_file_hex sha512_224_file_b64 sha512_224_file_b64u )] ); |
3 | 3 | |
4 | 4 | use strict; |
5 | 5 | use warnings; |
6 | our $VERSION = '0.066'; | |
6 | our $VERSION = '0.067'; | |
7 | 7 | |
8 | 8 | use base qw(Crypt::Digest Exporter); |
9 | 9 | our %EXPORT_TAGS = ( all => [qw( sha512_256 sha512_256_hex sha512_256_b64 sha512_256_b64u sha512_256_file sha512_256_file_hex sha512_256_file_b64 sha512_256_file_b64u )] ); |
1 | 1 | |
2 | 2 | use strict; |
3 | 3 | use warnings; |
4 | our $VERSION = '0.066'; | |
4 | our $VERSION = '0.067'; | |
5 | 5 | |
6 | 6 | use Carp; |
7 | 7 | $Carp::Internal{(__PACKAGE__)}++; |
3 | 3 | |
4 | 4 | use strict; |
5 | 5 | use warnings; |
6 | our $VERSION = '0.066'; | |
6 | our $VERSION = '0.067'; | |
7 | 7 | |
8 | 8 | use base qw(Crypt::Digest Exporter); |
9 | 9 | our %EXPORT_TAGS = ( all => [qw( tiger192 tiger192_hex tiger192_b64 tiger192_b64u tiger192_file tiger192_file_hex tiger192_file_b64 tiger192_file_b64u )] ); |
3 | 3 | |
4 | 4 | use strict; |
5 | 5 | use warnings; |
6 | our $VERSION = '0.066'; | |
6 | our $VERSION = '0.067'; | |
7 | 7 | |
8 | 8 | use base qw(Crypt::Digest Exporter); |
9 | 9 | our %EXPORT_TAGS = ( all => [qw( whirlpool whirlpool_hex whirlpool_b64 whirlpool_b64u whirlpool_file whirlpool_file_hex whirlpool_file_b64 whirlpool_file_b64u )] ); |
1 | 1 | |
2 | 2 | use strict; |
3 | 3 | use warnings; |
4 | our $VERSION = '0.066'; | |
5 | ||
6 | require Exporter; our @ISA = qw(Exporter); ### use Exporter 'import'; | |
4 | our $VERSION = '0.067'; | |
5 | ||
6 | require Exporter; our @ISA = qw(Exporter); ### use Exporter 5.57 'import'; | |
7 | 7 | our %EXPORT_TAGS = ( all => [qw( digest_data digest_data_hex digest_data_b64 digest_data_b64u digest_file digest_file_hex digest_file_b64 digest_file_b64u )] ); |
8 | 8 | our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } ); |
9 | 9 | our @EXPORT = qw(); |
1 | 1 | |
2 | 2 | use strict; |
3 | 3 | use warnings; |
4 | our $VERSION = '0.066'; | |
4 | our $VERSION = '0.067'; | |
5 | 5 | |
6 | require Exporter; our @ISA = qw(Exporter); ### use Exporter 'import'; | |
6 | require Exporter; our @ISA = qw(Exporter); ### use Exporter 5.57 'import'; | |
7 | 7 | our %EXPORT_TAGS = ( all => [qw(pbkdf1 pbkdf2 hkdf hkdf_expand hkdf_extract)] ); |
8 | 8 | our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } ); |
9 | 9 | our @EXPORT = qw(); |
3 | 3 | |
4 | 4 | use strict; |
5 | 5 | use warnings; |
6 | our $VERSION = '0.066'; | |
6 | our $VERSION = '0.067'; | |
7 | 7 | |
8 | 8 | use base qw(Crypt::Mac Exporter); |
9 | 9 | our %EXPORT_TAGS = ( all => [qw( blake2b blake2b_hex blake2b_b64 blake2b_b64u )] ); |
3 | 3 | |
4 | 4 | use strict; |
5 | 5 | use warnings; |
6 | our $VERSION = '0.066'; | |
6 | our $VERSION = '0.067'; | |
7 | 7 | |
8 | 8 | use base qw(Crypt::Mac Exporter); |
9 | 9 | our %EXPORT_TAGS = ( all => [qw( blake2s blake2s_hex blake2s_b64 blake2s_b64u )] ); |
3 | 3 | |
4 | 4 | use strict; |
5 | 5 | use warnings; |
6 | our $VERSION = '0.066'; | |
6 | our $VERSION = '0.067'; | |
7 | 7 | |
8 | 8 | use base qw(Crypt::Mac Exporter); |
9 | 9 | our %EXPORT_TAGS = ( all => [qw( f9 f9_hex f9_b64 f9_b64u )] ); |
3 | 3 | |
4 | 4 | use strict; |
5 | 5 | use warnings; |
6 | our $VERSION = '0.066'; | |
6 | our $VERSION = '0.067'; | |
7 | 7 | |
8 | 8 | use base qw(Crypt::Mac Exporter); |
9 | 9 | our %EXPORT_TAGS = ( all => [qw( hmac hmac_hex hmac_b64 hmac_b64u )] ); |
3 | 3 | |
4 | 4 | use strict; |
5 | 5 | use warnings; |
6 | our $VERSION = '0.066'; | |
6 | our $VERSION = '0.067'; | |
7 | 7 | |
8 | 8 | use base qw(Crypt::Mac Exporter); |
9 | 9 | our %EXPORT_TAGS = ( all => [qw( omac omac_hex omac_b64 omac_b64u )] ); |
3 | 3 | |
4 | 4 | use strict; |
5 | 5 | use warnings; |
6 | our $VERSION = '0.066'; | |
6 | our $VERSION = '0.067'; | |
7 | 7 | |
8 | 8 | use base qw(Crypt::Mac Exporter); |
9 | 9 | our %EXPORT_TAGS = ( all => [qw( pmac pmac_hex pmac_b64 pmac_b64u )] ); |
3 | 3 | |
4 | 4 | use strict; |
5 | 5 | use warnings; |
6 | our $VERSION = '0.066'; | |
6 | our $VERSION = '0.067'; | |
7 | 7 | |
8 | 8 | use base qw(Crypt::Mac Exporter); |
9 | 9 | our %EXPORT_TAGS = ( all => [qw( pelican pelican_hex pelican_b64 pelican_b64u )] ); |
3 | 3 | |
4 | 4 | use strict; |
5 | 5 | use warnings; |
6 | our $VERSION = '0.066'; | |
6 | our $VERSION = '0.067'; | |
7 | 7 | |
8 | 8 | use base qw(Crypt::Mac Exporter); |
9 | 9 | our %EXPORT_TAGS = ( all => [qw( poly1305 poly1305_hex poly1305_b64 poly1305_b64u )] ); |
3 | 3 | |
4 | 4 | use strict; |
5 | 5 | use warnings; |
6 | our $VERSION = '0.066'; | |
6 | our $VERSION = '0.067'; | |
7 | 7 | |
8 | 8 | use base qw(Crypt::Mac Exporter); |
9 | 9 | our %EXPORT_TAGS = ( all => [qw( xcbc xcbc_hex xcbc_b64 xcbc_b64u )] ); |
1 | 1 | |
2 | 2 | use strict; |
3 | 3 | use warnings; |
4 | our $VERSION = '0.066'; | |
4 | our $VERSION = '0.067'; | |
5 | 5 | |
6 | 6 | use Carp; |
7 | 7 | $Carp::Internal{(__PACKAGE__)}++; |
1 | 1 | |
2 | 2 | use strict; |
3 | 3 | use warnings; |
4 | our $VERSION = '0.066'; | |
4 | our $VERSION = '0.067'; | |
5 | 5 | |
6 | 6 | require Exporter; our @ISA = qw(Exporter); ### use Exporter 5.57 'import'; |
7 | 7 | use Carp 'croak'; |
3 | 3 | |
4 | 4 | use strict; |
5 | 5 | use warnings; |
6 | our $VERSION = '0.066'; | |
6 | our $VERSION = '0.067'; | |
7 | 7 | |
8 | 8 | use Crypt::Cipher; |
9 | 9 |
3 | 3 | |
4 | 4 | use strict; |
5 | 5 | use warnings; |
6 | our $VERSION = '0.066'; | |
6 | our $VERSION = '0.067'; | |
7 | 7 | |
8 | 8 | use Crypt::Cipher; |
9 | 9 |
3 | 3 | |
4 | 4 | use strict; |
5 | 5 | use warnings; |
6 | our $VERSION = '0.066'; | |
6 | our $VERSION = '0.067'; | |
7 | 7 | |
8 | 8 | use Crypt::Cipher; |
9 | 9 |
3 | 3 | |
4 | 4 | use strict; |
5 | 5 | use warnings; |
6 | our $VERSION = '0.066'; | |
6 | our $VERSION = '0.067'; | |
7 | 7 | |
8 | 8 | use Crypt::Cipher; |
9 | 9 |
3 | 3 | |
4 | 4 | use strict; |
5 | 5 | use warnings; |
6 | our $VERSION = '0.066'; | |
6 | our $VERSION = '0.067'; | |
7 | 7 | |
8 | 8 | use Crypt::Cipher; |
9 | 9 |
1 | 1 | |
2 | 2 | use strict; |
3 | 3 | use warnings; |
4 | our $VERSION = '0.066'; | |
4 | our $VERSION = '0.067'; | |
5 | 5 | |
6 | 6 | ### not used |
7 | 7 |
1 | 1 | |
2 | 2 | use strict; |
3 | 3 | use warnings; |
4 | our $VERSION = '0.066'; | |
5 | ||
6 | require Exporter; our @ISA = qw(Exporter); ### use Exporter 'import'; | |
4 | our $VERSION = '0.067'; | |
5 | ||
6 | require Exporter; our @ISA = qw(Exporter); ### use Exporter 5.57 'import'; | |
7 | 7 | our %EXPORT_TAGS = ( all => [qw( dh_shared_secret )] ); |
8 | 8 | our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } ); |
9 | 9 | our @EXPORT = qw(); |
1 | 1 | |
2 | 2 | use strict; |
3 | 3 | use warnings; |
4 | our $VERSION = '0.066'; | |
5 | ||
6 | require Exporter; our @ISA = qw(Exporter); ### use Exporter 'import'; | |
4 | our $VERSION = '0.067'; | |
5 | ||
6 | require Exporter; our @ISA = qw(Exporter); ### use Exporter 5.57 'import'; | |
7 | 7 | our %EXPORT_TAGS = ( all => [qw( dsa_encrypt dsa_decrypt dsa_sign_message dsa_verify_message dsa_sign_hash dsa_verify_hash )] ); |
8 | 8 | our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } ); |
9 | 9 | our @EXPORT = qw(); |
1 | 1 | |
2 | 2 | use strict; |
3 | 3 | use warnings; |
4 | our $VERSION = '0.066'; | |
5 | ||
6 | require Exporter; our @ISA = qw(Exporter); ### use Exporter 'import'; | |
4 | our $VERSION = '0.067'; | |
5 | ||
6 | require Exporter; our @ISA = qw(Exporter); ### use Exporter 5.57 'import'; | |
7 | 7 | our %EXPORT_TAGS = ( all => [qw( ecc_encrypt ecc_decrypt ecc_sign_message ecc_verify_message ecc_sign_hash ecc_verify_hash ecc_shared_secret )] ); |
8 | 8 | our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } ); |
9 | 9 | our @EXPORT = qw(); |
0 | package Crypt::PK::Ed25519; | |
1 | ||
2 | use strict; | |
3 | use warnings; | |
4 | our $VERSION = '0.067'; | |
5 | ||
6 | require Exporter; our @ISA = qw(Exporter); ### use Exporter 5.57 'import'; | |
7 | our %EXPORT_TAGS = ( all => [qw( )] ); | |
8 | our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } ); | |
9 | our @EXPORT = qw(); | |
10 | ||
11 | use Carp; | |
12 | $Carp::Internal{(__PACKAGE__)}++; | |
13 | use CryptX; | |
14 | use Crypt::PK; | |
15 | use Crypt::Misc qw(read_rawfile encode_b64u decode_b64u encode_b64 decode_b64 pem_to_der der_to_pem); | |
16 | ||
17 | sub new { | |
18 | my $self = shift->_new(); | |
19 | return @_ > 0 ? $self->import_key(@_) : $self; | |
20 | } | |
21 | ||
22 | sub import_key_raw { | |
23 | my ($self, $key, $type) = @_; | |
24 | croak "FATAL: undefined key" unless $key; | |
25 | croak "FATAL: invalid key" unless length($key) == 32; | |
26 | croak "FATAL: undefined type" unless $type; | |
27 | return $self->_import_raw($key, 1) if $type eq 'private'; | |
28 | return $self->_import_raw($key, 0) if $type eq 'public'; | |
29 | croak "FATAL: invalid key type '$type'"; | |
30 | } | |
31 | ||
32 | sub import_key { | |
33 | my ($self, $key, $password) = @_; | |
34 | local $SIG{__DIE__} = \&CryptX::_croak; | |
35 | croak "FATAL: undefined key" unless $key; | |
36 | ||
37 | # special case | |
38 | if (ref($key) eq 'HASH') { | |
39 | if ($key->{kty} && $key->{kty} eq "OKP" && $key->{crv} && $key->{crv} eq 'Ed25519') { | |
40 | # JWK-like structure e.g. | |
41 | # {"kty":"OKP","crv":"Ed25519","d":"...","x":"..."} | |
42 | return $self->_import_raw(decode_b64u($key->{d}), 1) if $key->{d}; # private | |
43 | return $self->_import_raw(decode_b64u($key->{x}), 0) if $key->{x}; # public | |
44 | } | |
45 | if ($key->{curve} && $key->{curve} eq "ed25519" && ($key->{priv} || $key->{pub})) { | |
46 | # hash exported via key2hash | |
47 | return $self->_import_raw(pack("H*", $key->{priv}), 1) if $key->{priv}; | |
48 | return $self->_import_raw(pack("H*", $key->{pub}), 0) if $key->{pub}; | |
49 | } | |
50 | croak "FATAL: unexpected Ed25519 key hash"; | |
51 | } | |
52 | ||
53 | my $data; | |
54 | if (ref($key) eq 'SCALAR') { | |
55 | $data = $$key; | |
56 | } | |
57 | elsif (-f $key) { | |
58 | $data = read_rawfile($key); | |
59 | } | |
60 | else { | |
61 | croak "FATAL: non-existing file '$key'"; | |
62 | } | |
63 | croak "FATAL: invalid key data" unless $data; | |
64 | ||
65 | if ($data =~ /-----BEGIN PUBLIC KEY-----(.*?)-----END/sg) { | |
66 | $data = pem_to_der($data, $password); | |
67 | return $self->_import($data); | |
68 | } | |
69 | elsif ($data =~ /-----BEGIN PRIVATE KEY-----(.*?)-----END/sg) { | |
70 | $data = pem_to_der($data, $password); | |
71 | return $self->_import_pkcs8($data, $password); | |
72 | } | |
73 | elsif ($data =~ /-----BEGIN ENCRYPTED PRIVATE KEY-----(.*?)-----END/sg) { | |
74 | $data = pem_to_der($data, $password); | |
75 | return $self->_import_pkcs8($data, $password); | |
76 | } | |
77 | elsif ($data =~ /-----BEGIN ED25519 PRIVATE KEY-----(.*?)-----END/sg) { | |
78 | $data = pem_to_der($data, $password); | |
79 | return $self->_import_pkcs8($data, $password); | |
80 | } | |
81 | elsif ($data =~ /^\s*(\{.*?\})\s*$/s) { # JSON | |
82 | my $h = CryptX::_decode_json("$1"); | |
83 | if ($h->{kty} && $h->{kty} eq "OKP" && $h->{crv} && $h->{crv} eq 'Ed25519') { | |
84 | return $self->_import_raw(decode_b64u($h->{d}), 1) if $h->{d}; # private | |
85 | return $self->_import_raw(decode_b64u($h->{x}), 0) if $h->{x}; # public | |
86 | } | |
87 | } | |
88 | elsif ($data =~ /-----BEGIN CERTIFICATE-----(.*?)-----END CERTIFICATE-----/sg) { | |
89 | $data = pem_to_der($data); | |
90 | return $self->_import_x509($data); | |
91 | } | |
92 | elsif ($data =~ /-----BEGIN OPENSSH PRIVATE KEY-----(.*?)-----END/sg) { | |
93 | #XXX-FIXME-TODO | |
94 | # https://crypto.stackexchange.com/questions/71789/openssh-ed2215-private-key-format | |
95 | # https://cvsweb.openbsd.org/src/usr.bin/ssh/PROTOCOL.key?annotate=HEAD | |
96 | croak "FATAL: OPENSSH PRIVATE KEY not supported"; | |
97 | } | |
98 | elsif ($data =~ /---- BEGIN SSH2 PUBLIC KEY ----(.*?)---- END SSH2 PUBLIC KEY ----/sg) { | |
99 | $data = pem_to_der($data); | |
100 | my ($typ, $pubkey) = Crypt::PK::_ssh_parse($data); | |
101 | return $self->_import_raw($pubkey, 0) if $typ eq 'ssh-ed25519' && length($pubkey) == 32; | |
102 | } | |
103 | elsif ($data =~ /(ssh-ed25519)\s+(\S+)/) { | |
104 | $data = decode_b64("$2"); | |
105 | my ($typ, $pubkey) = Crypt::PK::_ssh_parse($data); | |
106 | return $self->_import_raw($pubkey, 0) if $typ eq 'ssh-ed25519' && length($pubkey) == 32; | |
107 | } | |
108 | elsif (length($data) == 32) { | |
109 | croak "FATAL: use import_key_raw() to load raw (32 bytes) Ed25519 key"; | |
110 | } | |
111 | else { | |
112 | my $rv = eval { $self->_import($data) } || | |
113 | eval { $self->_import_pkcs8($data, $password) } || | |
114 | eval { $self->_import_x509($data) }; | |
115 | return $rv if $rv; | |
116 | } | |
117 | croak "FATAL: invalid or unsupported Ed25519 key format"; | |
118 | } | |
119 | ||
120 | sub export_key_pem { | |
121 | my ($self, $type, $password, $cipher) = @_; | |
122 | local $SIG{__DIE__} = \&CryptX::_croak; | |
123 | my $key = $self->export_key_der($type||''); | |
124 | return unless $key; | |
125 | return der_to_pem($key, "ED25519 PRIVATE KEY", $password, $cipher) if substr($type, 0, 7) eq 'private'; | |
126 | return der_to_pem($key, "PUBLIC KEY") if substr($type,0, 6) eq 'public'; | |
127 | } | |
128 | ||
129 | sub export_key_jwk { | |
130 | my ($self, $type, $wanthash) = @_; | |
131 | local $SIG{__DIE__} = \&CryptX::_croak; | |
132 | my $kh = $self->key2hash; | |
133 | return unless $kh; | |
134 | my $hash = { kty => "OKP", crv => "Ed25519" }; | |
135 | $hash->{x} = encode_b64u(pack("H*", $kh->{pub})); | |
136 | $hash->{d} = encode_b64u(pack("H*", $kh->{priv})) if $type && $type eq 'private' && $kh->{priv}; | |
137 | return $wanthash ? $hash : CryptX::_encode_json($hash); | |
138 | } | |
139 | ||
140 | sub CLONE_SKIP { 1 } # prevent cloning | |
141 | ||
142 | 1; | |
143 | ||
144 | =pod | |
145 | ||
146 | =head1 NAME | |
147 | ||
148 | Crypt::PK::Ed25519 - Digital signature based on Ed25519 | |
149 | ||
150 | =head1 SYNOPSIS | |
151 | ||
152 | use Crypt::PK::Ed25519; | |
153 | ||
154 | #Signature: Alice | |
155 | my $priv = Crypt::PK::Ed25519->new('Alice_priv_ed25519.der'); | |
156 | my $sig = $priv->sign_message($message); | |
157 | ||
158 | #Signature: Bob (received $message + $sig) | |
159 | my $pub = Crypt::PK::Ed25519->new('Alice_pub_ed25519.der'); | |
160 | $pub->verify_message($sig, $message) or die "ERROR"; | |
161 | ||
162 | #Load key | |
163 | my $pk = Crypt::PK::Ed25519->new; | |
164 | my $pk_hex = "A05D1AEA5830AC9A65CDFB384660D497E3697C46B419CF2CEC85DE8BD245459D"; | |
165 | $pk->import_key_raw(pack("H*", $pk_hex), "public"); | |
166 | my $sk = Crypt::PK::Ed25519->new; | |
167 | my $sk_hex = "45C109BA6FD24E8B67D23EFB6B92D99CD457E2137172C0D749FE2B5A0C142DAD"; | |
168 | $sk->import_key_raw(pack("H*", $sk_hex), "private"); | |
169 | ||
170 | #Key generation | |
171 | my $pk = Crypt::PK::Ed25519->new->generate_key; | |
172 | my $private_der = $pk->export_key_der('private'); | |
173 | my $public_der = $pk->export_key_der('public'); | |
174 | my $private_pem = $pk->export_key_pem('private'); | |
175 | my $public_pem = $pk->export_key_pem('public'); | |
176 | my $private_raw = $pk->export_key_raw('private'); | |
177 | my $public_raw = $pk->export_key_raw('public'); | |
178 | my $private_jwk = $pk->export_key_jwk('private'); | |
179 | my $public_jwk = $pk->export_key_jwk('public'); | |
180 | ||
181 | =head1 DESCRIPTION | |
182 | ||
183 | I<Since: CryptX-0.067> | |
184 | ||
185 | =head1 METHODS | |
186 | ||
187 | =head2 new | |
188 | ||
189 | my $pk = Crypt::PK::Ed25519->new(); | |
190 | #or | |
191 | my $pk = Crypt::PK::Ed25519->new($priv_or_pub_key_filename); | |
192 | #or | |
193 | my $pk = Crypt::PK::Ed25519->new(\$buffer_containing_priv_or_pub_key); | |
194 | ||
195 | Support for password protected PEM keys | |
196 | ||
197 | my $pk = Crypt::PK::Ed25519->new($priv_pem_key_filename, $password); | |
198 | #or | |
199 | my $pk = Crypt::PK::Ed25519->new(\$buffer_containing_priv_pem_key, $password); | |
200 | ||
201 | =head2 generate_key | |
202 | ||
203 | Uses Yarrow-based cryptographically strong random number generator seeded with | |
204 | random data taken from C</dev/random> (UNIX) or C<CryptGenRandom> (Win32). | |
205 | ||
206 | $pk->generate_key; | |
207 | ||
208 | =head2 import_key | |
209 | ||
210 | Loads private or public key in DER or PEM format. | |
211 | ||
212 | $pk->import_key($filename); | |
213 | #or | |
214 | $pk->import_key(\$buffer_containing_key); | |
215 | ||
216 | Support for password protected PEM keys: | |
217 | ||
218 | $pk->import_key($filename, $password); | |
219 | #or | |
220 | $pk->import_key(\$buffer_containing_key, $password); | |
221 | ||
222 | Loading private or public keys form perl hash: | |
223 | ||
224 | $pk->import_key($hashref); | |
225 | ||
226 | # the $hashref is either a key exported via key2hash | |
227 | $pk->import_key({ | |
228 | curve => "ed25519", | |
229 | pub => "A05D1AEA5830AC9A65CDFB384660D497E3697C46B419CF2CEC85DE8BD245459D", | |
230 | priv => "45C109BA6FD24E8B67D23EFB6B92D99CD457E2137172C0D749FE2B5A0C142DAD", | |
231 | }); | |
232 | ||
233 | # or a hash with items corresponding to JWK (JSON Web Key) | |
234 | $pk->import_key({ | |
235 | kty => "OKP", | |
236 | crv => "Ed25519", | |
237 | d => "RcEJum_STotn0j77a5LZnNRX4hNxcsDXSf4rWgwULa0", | |
238 | x => "oF0a6lgwrJplzfs4RmDUl-NpfEa0Gc8s7IXei9JFRZ0", | |
239 | }); | |
240 | ||
241 | Supported key formats: | |
242 | ||
243 | # all formats can be loaded from a file | |
244 | my $pk = Crypt::PK::Ed25519->new($filename); | |
245 | ||
246 | # or from a buffer containing the key | |
247 | my $pk = Crypt::PK::Ed25519->new(\$buffer_with_key); | |
248 | ||
249 | =over | |
250 | ||
251 | =item * Ed25519 private keys in PEM format | |
252 | ||
253 | -----BEGIN ED25519 PRIVATE KEY----- | |
254 | MC4CAQAwBQYDK2VwBCIEIEXBCbpv0k6LZ9I++2uS2ZzUV+ITcXLA10n+K1oMFC2t | |
255 | -----END ED25519 PRIVATE KEY----- | |
256 | ||
257 | =item * Ed25519 private keys in password protected PEM format | |
258 | ||
259 | -----BEGIN ED25519 PRIVATE KEY----- | |
260 | Proc-Type: 4,ENCRYPTED | |
261 | DEK-Info: DES-CBC,6A64D756D49C1EFF | |
262 | ||
263 | 8xQ7OyfQ10IITNEKcJGZA53Z1yk+NJQU7hrKqXwChZtgWNInhMBJRl9pozLKDSkH | |
264 | v7u6EOve8NY= | |
265 | -----END ED25519 PRIVATE KEY----- | |
266 | ||
267 | =item * PKCS#8 private keys | |
268 | ||
269 | -----BEGIN PRIVATE KEY----- | |
270 | MC4CAQAwBQYDK2VwBCIEIEXBCbpv0k6LZ9I++2uS2ZzUV+ITcXLA10n+K1oMFC2t | |
271 | -----END PRIVATE KEY----- | |
272 | ||
273 | =item * PKCS#8 encrypted private keys | |
274 | ||
275 | -----BEGIN ENCRYPTED PRIVATE KEY----- | |
276 | MIGHMEsGCSqGSIb3DQEFDTA+MCkGCSqGSIb3DQEFDDAcBAjPx9JkdpRH2QICCAAw | |
277 | DAYIKoZIhvcNAgkFADARBgUrDgMCBwQIWWieQojaWTcEOGj43SxqHUys4Eb2M27N | |
278 | AkhqpmhosOxKrpGi0L3h8m8ipHE8EwI94NeOMsjfVw60aJuCrssY5vKN | |
279 | -----END ENCRYPTED PRIVATE KEY----- | |
280 | ||
281 | =item * Ed25519 public keys in PEM format | |
282 | ||
283 | -----BEGIN PUBLIC KEY----- | |
284 | MCowBQYDK2VwAyEAoF0a6lgwrJplzfs4RmDUl+NpfEa0Gc8s7IXei9JFRZ0= | |
285 | -----END PUBLIC KEY----- | |
286 | ||
287 | =item * Ed25519 public key from X509 certificate | |
288 | ||
289 | -----BEGIN CERTIFICATE----- | |
290 | MIIBODCB66ADAgECAhRWDU9FZBBUZ7KTdX8f7Bco8jsoaTAFBgMrZXAwETEPMA0G | |
291 | A1UEAwwGQ3J5cHRYMCAXDTIwMDExOTEzMDIwMloYDzIyOTMxMTAyMTMwMjAyWjAR | |
292 | MQ8wDQYDVQQDDAZDcnlwdFgwKjAFBgMrZXADIQCgXRrqWDCsmmXN+zhGYNSX42l8 | |
293 | RrQZzyzshd6L0kVFnaNTMFEwHQYDVR0OBBYEFHCGFtVibAxxWYyRt5wazMpqSZDV | |
294 | MB8GA1UdIwQYMBaAFHCGFtVibAxxWYyRt5wazMpqSZDVMA8GA1UdEwEB/wQFMAMB | |
295 | Af8wBQYDK2VwA0EAqG/+98smzqF/wmFX3zHXSaA67as202HnBJod1Tiurw1f+lr3 | |
296 | BX6OMtsDpgRq9O77IF1Qyx/MdJEwwErczOIbAA== | |
297 | -----END CERTIFICATE----- | |
298 | ||
299 | =item * SSH public Ed25519 keys | |
300 | ||
301 | ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIL0XsiFcRDp6Hpsoak8OdiiBMJhM2UKszNTxoGS7dJ++ | |
302 | ||
303 | =item * SSH public Ed25519 keys (RFC-4716 format) | |
304 | ||
305 | ---- BEGIN SSH2 PUBLIC KEY ---- | |
306 | Comment: "256-bit ED25519, converted from OpenSSH" | |
307 | AAAAC3NzaC1lZDI1NTE5AAAAIL0XsiFcRDp6Hpsoak8OdiiBMJhM2UKszNTxoGS7dJ++ | |
308 | ---- END SSH2 PUBLIC KEY ---- | |
309 | ||
310 | =item * Ed25519 private keys in JSON Web Key (JWK) format | |
311 | ||
312 | See L<https://tools.ietf.org/html/rfc8037> | |
313 | ||
314 | { | |
315 | "kty":"OKP", | |
316 | "crv":"Ed25519", | |
317 | "x":"oF0a6lgwrJplzfs4RmDUl-NpfEa0Gc8s7IXei9JFRZ0", | |
318 | "d":"RcEJum_STotn0j77a5LZnNRX4hNxcsDXSf4rWgwULa0", | |
319 | } | |
320 | ||
321 | B<BEWARE:> For JWK support you need to have L<JSON::PP>, L<JSON::XS> or L<Cpanel::JSON::XS> module. | |
322 | ||
323 | =item * Ed25519 public keys in JSON Web Key (JWK) format | |
324 | ||
325 | { | |
326 | "kty":"OKP", | |
327 | "crv":"Ed25519", | |
328 | "x":"oF0a6lgwrJplzfs4RmDUl-NpfEa0Gc8s7IXei9JFRZ0", | |
329 | } | |
330 | ||
331 | B<BEWARE:> For JWK support you need to have L<JSON::PP>, L<JSON::XS> or L<Cpanel::JSON::XS> module. | |
332 | ||
333 | =back | |
334 | ||
335 | =head2 import_key_raw | |
336 | ||
337 | Import raw public/private key - can load raw key data exported by L</export_key_raw>. | |
338 | ||
339 | $pk->import_key_raw($key, 'public'); | |
340 | $pk->import_key_raw($key, 'private'); | |
341 | ||
342 | =head2 export_key_der | |
343 | ||
344 | my $private_der = $pk->export_key_der('private'); | |
345 | #or | |
346 | my $public_der = $pk->export_key_der('public'); | |
347 | ||
348 | =head2 export_key_pem | |
349 | ||
350 | my $private_pem = $pk->export_key_pem('private'); | |
351 | #or | |
352 | my $public_pem = $pk->export_key_pem('public'); | |
353 | ||
354 | Support for password protected PEM keys | |
355 | ||
356 | my $private_pem = $pk->export_key_pem('private', $password); | |
357 | #or | |
358 | my $private_pem = $pk->export_key_pem('private', $password, $cipher); | |
359 | ||
360 | # supported ciphers: 'DES-CBC' | |
361 | # 'DES-EDE3-CBC' | |
362 | # 'SEED-CBC' | |
363 | # 'CAMELLIA-128-CBC' | |
364 | # 'CAMELLIA-192-CBC' | |
365 | # 'CAMELLIA-256-CBC' | |
366 | # 'AES-128-CBC' | |
367 | # 'AES-192-CBC' | |
368 | # 'AES-256-CBC' (DEFAULT) | |
369 | ||
370 | =head2 export_key_jwk | |
371 | ||
372 | Exports public/private keys as a JSON Web Key (JWK). | |
373 | ||
374 | my $private_json_text = $pk->export_key_jwk('private'); | |
375 | #or | |
376 | my $public_json_text = $pk->export_key_jwk('public'); | |
377 | ||
378 | Also exports public/private keys as a perl HASH with JWK structure. | |
379 | ||
380 | my $jwk_hash = $pk->export_key_jwk('private', 1); | |
381 | #or | |
382 | my $jwk_hash = $pk->export_key_jwk('public', 1); | |
383 | ||
384 | B<BEWARE:> For JWK support you need to have L<JSON::PP>, L<JSON::XS> or L<Cpanel::JSON::XS> module. | |
385 | ||
386 | =head2 export_key_raw | |
387 | ||
388 | Export raw public/private key | |
389 | ||
390 | my $private_bytes = $pk->export_key_raw('private'); | |
391 | #or | |
392 | my $public_bytes = $pk->export_key_raw('public'); | |
393 | ||
394 | =head2 sign_message | |
395 | ||
396 | my $signature = $priv->sign_message($message); | |
397 | ||
398 | =head2 verify_message | |
399 | ||
400 | my $valid = $pub->verify_message($signature, $message) | |
401 | ||
402 | =head2 is_private | |
403 | ||
404 | my $rv = $pk->is_private; | |
405 | # 1 .. private key loaded | |
406 | # 0 .. public key loaded | |
407 | # undef .. no key loaded | |
408 | ||
409 | =head2 key2hash | |
410 | ||
411 | my $hash = $pk->key2hash; | |
412 | ||
413 | # returns hash like this (or undef if no key loaded): | |
414 | { | |
415 | curve => "ed25519", | |
416 | # raw public key as a hexadecimal string | |
417 | pub => "A05D1AEA5830AC9A65CDFB384660D497E3697C46B419CF2CEC85DE8BD245459D", | |
418 | # raw private key as a hexadecimal string. undef if key is public only | |
419 | priv => "45C109BA6FD24E8B67D23EFB6B92D99CD457E2137172C0D749FE2B5A0C142DAD", | |
420 | } | |
421 | ||
422 | =head1 SEE ALSO | |
423 | ||
424 | =over | |
425 | ||
426 | =item * L<https://en.wikipedia.org/wiki/EdDSA#Ed25519> | |
427 | ||
428 | =item * L<https://en.wikipedia.org/wiki/Curve25519> | |
429 | ||
430 | =item * L<https://tools.ietf.org/html/rfc8032> | |
431 | ||
432 | =back | |
433 | ||
434 | =cut |
1 | 1 | |
2 | 2 | use strict; |
3 | 3 | use warnings; |
4 | our $VERSION = '0.066'; | |
5 | ||
6 | require Exporter; our @ISA = qw(Exporter); ### use Exporter 'import'; | |
4 | our $VERSION = '0.067'; | |
5 | ||
6 | require Exporter; our @ISA = qw(Exporter); ### use Exporter 5.57 'import'; | |
7 | 7 | our %EXPORT_TAGS = ( all => [qw(rsa_encrypt rsa_decrypt rsa_sign_message rsa_verify_message rsa_sign_hash rsa_verify_hash)] ); |
8 | 8 | our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } ); |
9 | 9 | our @EXPORT = qw(); |
0 | package Crypt::PK::X25519; | |
1 | ||
2 | use strict; | |
3 | use warnings; | |
4 | our $VERSION = '0.067'; | |
5 | ||
6 | require Exporter; our @ISA = qw(Exporter); ### use Exporter 5.57 'import'; | |
7 | our %EXPORT_TAGS = ( all => [qw( )] ); | |
8 | our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } ); | |
9 | our @EXPORT = qw(); | |
10 | ||
11 | use Carp; | |
12 | $Carp::Internal{(__PACKAGE__)}++; | |
13 | use CryptX; | |
14 | use Crypt::PK; | |
15 | use Crypt::Misc qw(read_rawfile encode_b64u decode_b64u encode_b64 decode_b64 pem_to_der der_to_pem); | |
16 | ||
17 | sub new { | |
18 | my $self = shift->_new(); | |
19 | return @_ > 0 ? $self->import_key(@_) : $self; | |
20 | } | |
21 | ||
22 | sub import_key_raw { | |
23 | my ($self, $key, $type) = @_; | |
24 | croak "FATAL: undefined key" unless $key; | |
25 | croak "FATAL: invalid key" unless length($key) == 32; | |
26 | croak "FATAL: undefined type" unless $type; | |
27 | return $self->_import_raw($key, 1) if $type eq 'private'; | |
28 | return $self->_import_raw($key, 0) if $type eq 'public'; | |
29 | croak "FATAL: invalid key type '$type'"; | |
30 | } | |
31 | ||
32 | sub import_key { | |
33 | my ($self, $key, $password) = @_; | |
34 | local $SIG{__DIE__} = \&CryptX::_croak; | |
35 | croak "FATAL: undefined key" unless $key; | |
36 | ||
37 | # special case | |
38 | if (ref($key) eq 'HASH') { | |
39 | if ($key->{kty} && $key->{kty} eq "OKP" && $key->{crv} && $key->{crv} eq 'X25519') { | |
40 | # JWK-like structure e.g. | |
41 | # {"kty":"OKP","crv":"X25519","d":"...","x":"..."} | |
42 | return $self->_import_raw(decode_b64u($key->{d}), 1) if $key->{d}; # private | |
43 | return $self->_import_raw(decode_b64u($key->{x}), 0) if $key->{x}; # public | |
44 | } | |
45 | if ($key->{curve} && $key->{curve} eq "x25519" && ($key->{priv} || $key->{pub})) { | |
46 | # hash exported via key2hash | |
47 | return $self->_import_raw(pack("H*", $key->{priv}), 1) if $key->{priv}; | |
48 | return $self->_import_raw(pack("H*", $key->{pub}), 0) if $key->{pub}; | |
49 | } | |
50 | croak "FATAL: unexpected X25519 key hash"; | |
51 | } | |
52 | ||
53 | my $data; | |
54 | if (ref($key) eq 'SCALAR') { | |
55 | $data = $$key; | |
56 | } | |
57 | elsif (-f $key) { | |
58 | $data = read_rawfile($key); | |
59 | } | |
60 | else { | |
61 | croak "FATAL: non-existing file '$key'"; | |
62 | } | |
63 | croak "FATAL: invalid key data" unless $data; | |
64 | ||
65 | if ($data =~ /-----BEGIN PUBLIC KEY-----(.*?)-----END/sg) { | |
66 | $data = pem_to_der($data, $password); | |
67 | return $self->_import($data); | |
68 | } | |
69 | elsif ($data =~ /-----BEGIN PRIVATE KEY-----(.*?)-----END/sg) { | |
70 | $data = pem_to_der($data, $password); | |
71 | return $self->_import_pkcs8($data, $password); | |
72 | } | |
73 | elsif ($data =~ /-----BEGIN ENCRYPTED PRIVATE KEY-----(.*?)-----END/sg) { | |
74 | $data = pem_to_der($data, $password); | |
75 | return $self->_import_pkcs8($data, $password); | |
76 | } | |
77 | elsif ($data =~ /-----BEGIN X25519 PRIVATE KEY-----(.*?)-----END/sg) { | |
78 | $data = pem_to_der($data, $password); | |
79 | return $self->_import_pkcs8($data, $password); | |
80 | } | |
81 | elsif ($data =~ /^\s*(\{.*?\})\s*$/s) { # JSON | |
82 | my $h = CryptX::_decode_json("$1"); | |
83 | if ($h->{kty} && $h->{kty} eq "OKP" && $h->{crv} && $h->{crv} eq 'X25519') { | |
84 | return $self->_import_raw(decode_b64u($h->{d}), 1) if $h->{d}; # private | |
85 | return $self->_import_raw(decode_b64u($h->{x}), 0) if $h->{x}; # public | |
86 | } | |
87 | } | |
88 | elsif (length($data) == 32) { | |
89 | croak "FATAL: use import_key_raw() to load raw (32 bytes) X25519 key"; | |
90 | } | |
91 | else { | |
92 | my $rv = eval { $self->_import($data) } || | |
93 | eval { $self->_import_pkcs8($data, $password) } || | |
94 | eval { $self->_import_x509($data) }; | |
95 | return $rv if $rv; | |
96 | } | |
97 | croak "FATAL: invalid or unsupported X25519 key format"; | |
98 | } | |
99 | ||
100 | sub export_key_pem { | |
101 | my ($self, $type, $password, $cipher) = @_; | |
102 | local $SIG{__DIE__} = \&CryptX::_croak; | |
103 | my $key = $self->export_key_der($type||''); | |
104 | return unless $key; | |
105 | return der_to_pem($key, "X25519 PRIVATE KEY", $password, $cipher) if substr($type, 0, 7) eq 'private'; | |
106 | return der_to_pem($key, "PUBLIC KEY") if substr($type,0, 6) eq 'public'; | |
107 | } | |
108 | ||
109 | sub export_key_jwk { | |
110 | my ($self, $type, $wanthash) = @_; | |
111 | local $SIG{__DIE__} = \&CryptX::_croak; | |
112 | my $kh = $self->key2hash; | |
113 | return unless $kh; | |
114 | my $hash = { kty => "OKP", crv => "X25519" }; | |
115 | $hash->{x} = encode_b64u(pack("H*", $kh->{pub})); | |
116 | $hash->{d} = encode_b64u(pack("H*", $kh->{priv})) if $type && $type eq 'private' && $kh->{priv}; | |
117 | return $wanthash ? $hash : CryptX::_encode_json($hash); | |
118 | } | |
119 | ||
120 | sub CLONE_SKIP { 1 } # prevent cloning | |
121 | ||
122 | 1; | |
123 | ||
124 | =pod | |
125 | ||
126 | =head1 NAME | |
127 | ||
128 | Crypt::PK::X25519 - Asymmetric cryptography based on X25519 | |
129 | ||
130 | =head1 SYNOPSIS | |
131 | ||
132 | use Crypt::PK::X25519; | |
133 | ||
134 | #Shared secret | |
135 | my $priv = Crypt::PK::X25519->new('Alice_priv_x25519.der'); | |
136 | my $pub = Crypt::PK::X25519->new('Bob_pub_x25519.der'); | |
137 | my $shared_secret = $priv->shared_secret($pub); | |
138 | ||
139 | #Load key | |
140 | my $pk = Crypt::PK::X25519->new; | |
141 | my $pk_hex = "EA7806F721A8570512C8F6EFB4E8D620C49A529E4DF5EAA77DEC646FB1E87E41"; | |
142 | $pk->import_key_raw(pack("H*", $pk_hex), "public"); | |
143 | my $sk = Crypt::PK::X25519->new; | |
144 | my $sk_hex = "002F93D10BA5728D8DD8E9527721DABA3261C0BB1BEFDE7B4BBDAC631D454651"; | |
145 | $sk->import_key_raw(pack("H*", $sk_hex), "private"); | |
146 | ||
147 | #Key generation | |
148 | my $pk = Crypt::PK::X25519->new->generate_key; | |
149 | my $private_der = $pk->export_key_der('private'); | |
150 | my $public_der = $pk->export_key_der('public'); | |
151 | my $private_pem = $pk->export_key_pem('private'); | |
152 | my $public_pem = $pk->export_key_pem('public'); | |
153 | my $private_raw = $pk->export_key_raw('private'); | |
154 | my $public_raw = $pk->export_key_raw('public'); | |
155 | my $private_jwk = $pk->export_key_jwk('private'); | |
156 | my $public_jwk = $pk->export_key_jwk('public'); | |
157 | ||
158 | =head1 DESCRIPTION | |
159 | ||
160 | I<Since: CryptX-0.067> | |
161 | ||
162 | =head1 METHODS | |
163 | ||
164 | =head2 new | |
165 | ||
166 | my $pk = Crypt::PK::X25519->new(); | |
167 | #or | |
168 | my $pk = Crypt::PK::X25519->new($priv_or_pub_key_filename); | |
169 | #or | |
170 | my $pk = Crypt::PK::X25519->new(\$buffer_containing_priv_or_pub_key); | |
171 | ||
172 | Support for password protected PEM keys | |
173 | ||
174 | my $pk = Crypt::PK::X25519->new($priv_pem_key_filename, $password); | |
175 | #or | |
176 | my $pk = Crypt::PK::X25519->new(\$buffer_containing_priv_pem_key, $password); | |
177 | ||
178 | =head2 generate_key | |
179 | ||
180 | Uses Yarrow-based cryptographically strong random number generator seeded with | |
181 | random data taken from C</dev/random> (UNIX) or C<CryptGenRandom> (Win32). | |
182 | ||
183 | $pk->generate_key; | |
184 | ||
185 | =head2 import_key | |
186 | ||
187 | Loads private or public key in DER or PEM format. | |
188 | ||
189 | $pk->import_key($filename); | |
190 | #or | |
191 | $pk->import_key(\$buffer_containing_key); | |
192 | ||
193 | Support for password protected PEM keys: | |
194 | ||
195 | $pk->import_key($filename, $password); | |
196 | #or | |
197 | $pk->import_key(\$buffer_containing_key, $password); | |
198 | ||
199 | Loading private or public keys form perl hash: | |
200 | ||
201 | $pk->import_key($hashref); | |
202 | ||
203 | # the $hashref is either a key exported via key2hash | |
204 | $pk->import_key({ | |
205 | curve => "x25519", | |
206 | pub => "EA7806F721A8570512C8F6EFB4E8D620C49A529E4DF5EAA77DEC646FB1E87E41", | |
207 | priv => "002F93D10BA5728D8DD8E9527721DABA3261C0BB1BEFDE7B4BBDAC631D454651", | |
208 | }); | |
209 | ||
210 | # or a hash with items corresponding to JWK (JSON Web Key) | |
211 | $pk->import_key({ | |
212 | kty => "OKP", | |
213 | crv => "X25519", | |
214 | d => "AC-T0Qulco2N2OlSdyHaujJhwLsb7957S72sYx1FRlE", | |
215 | x => "6ngG9yGoVwUSyPbvtOjWIMSaUp5N9eqnfexkb7HofkE", | |
216 | }); | |
217 | ||
218 | Supported key formats: | |
219 | ||
220 | # all formats can be loaded from a file | |
221 | my $pk = Crypt::PK::X25519->new($filename); | |
222 | ||
223 | # or from a buffer containing the key | |
224 | my $pk = Crypt::PK::X25519->new(\$buffer_with_key); | |
225 | ||
226 | =over | |
227 | ||
228 | =item * X25519 private keys in PEM format | |
229 | ||
230 | -----BEGIN X25519 PRIVATE KEY----- | |
231 | MC4CAQAwBQYDK2VuBCIEIAAvk9ELpXKNjdjpUnch2royYcC7G+/ee0u9rGMdRUZR | |
232 | -----END X25519 PRIVATE KEY----- | |
233 | ||
234 | =item * X25519 private keys in password protected PEM format | |
235 | ||
236 | -----BEGIN X25519 PRIVATE KEY----- | |
237 | Proc-Type: 4,ENCRYPTED | |
238 | DEK-Info: DES-CBC,DEEFD3D6B714E75A | |
239 | ||
240 | dfFWP5bKn49aZ993NVAhQQPdFWgsTb4j8CWhRjGBVTPl6ITstAL17deBIRBwZb7h | |
241 | pAyIka81Kfs= | |
242 | -----END X25519 PRIVATE KEY----- | |
243 | ||
244 | =item * X25519 public keys in PEM format | |
245 | ||
246 | -----BEGIN PUBLIC KEY----- | |
247 | MCowBQYDK2VuAyEA6ngG9yGoVwUSyPbvtOjWIMSaUp5N9eqnfexkb7HofkE= | |
248 | -----END PUBLIC KEY----- | |
249 | ||
250 | =item * PKCS#8 private keys | |
251 | ||
252 | -----BEGIN PRIVATE KEY----- | |
253 | MC4CAQAwBQYDK2VuBCIEIAAvk9ELpXKNjdjpUnch2royYcC7G+/ee0u9rGMdRUZR | |
254 | -----END PRIVATE KEY----- | |
255 | ||
256 | =item * PKCS#8 encrypted private keys | |
257 | ||
258 | -----BEGIN ENCRYPTED PRIVATE KEY----- | |
259 | MIGHMEsGCSqGSIb3DQEFDTA+MCkGCSqGSIb3DQEFDDAcBAiS0NOFZmjJswICCAAw | |
260 | DAYIKoZIhvcNAgkFADARBgUrDgMCBwQIGd40Hdso8Y4EONSRCTrqvftl9hl3zbH9 | |
261 | 2QmHF1KJ4HDMdLDRxD7EynonCw2SV7BO+XNRHzw2yONqiTybfte7nk9t | |
262 | -----END ENCRYPTED PRIVATE KEY----- | |
263 | ||
264 | =item * X25519 private keys in JSON Web Key (JWK) format | |
265 | ||
266 | See L<https://tools.ietf.org/html/rfc8037> | |
267 | ||
268 | { | |
269 | "kty":"OKP", | |
270 | "crv":"X25519", | |
271 | "x":"6ngG9yGoVwUSyPbvtOjWIMSaUp5N9eqnfexkb7HofkE", | |
272 | "d":"AC-T0Qulco2N2OlSdyHaujJhwLsb7957S72sYx1FRlE", | |
273 | } | |
274 | ||
275 | B<BEWARE:> For JWK support you need to have L<JSON::PP>, L<JSON::XS> or L<Cpanel::JSON::XS> module. | |
276 | ||
277 | =item * X25519 public keys in JSON Web Key (JWK) format | |
278 | ||
279 | { | |
280 | "kty":"OKP", | |
281 | "crv":"X25519", | |
282 | "x":"6ngG9yGoVwUSyPbvtOjWIMSaUp5N9eqnfexkb7HofkE", | |
283 | } | |
284 | ||
285 | B<BEWARE:> For JWK support you need to have L<JSON::PP>, L<JSON::XS> or L<Cpanel::JSON::XS> module. | |
286 | ||
287 | =back | |
288 | ||
289 | =head2 import_key_raw | |
290 | ||
291 | Import raw public/private key - can load raw key data exported by L</export_key_raw>. | |
292 | ||
293 | $pk->import_key_raw($key, 'public'); | |
294 | $pk->import_key_raw($key, 'private'); | |
295 | ||
296 | =head2 export_key_der | |
297 | ||
298 | my $private_der = $pk->export_key_der('private'); | |
299 | #or | |
300 | my $public_der = $pk->export_key_der('public'); | |
301 | ||
302 | =head2 export_key_pem | |
303 | ||
304 | my $private_pem = $pk->export_key_pem('private'); | |
305 | #or | |
306 | my $public_pem = $pk->export_key_pem('public'); | |
307 | ||
308 | Support for password protected PEM keys | |
309 | ||
310 | my $private_pem = $pk->export_key_pem('private', $password); | |
311 | #or | |
312 | my $private_pem = $pk->export_key_pem('private', $password, $cipher); | |
313 | ||
314 | # supported ciphers: 'DES-CBC' | |
315 | # 'DES-EDE3-CBC' | |
316 | # 'SEED-CBC' | |
317 | # 'CAMELLIA-128-CBC' | |
318 | # 'CAMELLIA-192-CBC' | |
319 | # 'CAMELLIA-256-CBC' | |
320 | # 'AES-128-CBC' | |
321 | # 'AES-192-CBC' | |
322 | # 'AES-256-CBC' (DEFAULT) | |
323 | ||
324 | =head2 export_key_jwk | |
325 | ||
326 | Exports public/private keys as a JSON Web Key (JWK). | |
327 | ||
328 | my $private_json_text = $pk->export_key_jwk('private'); | |
329 | #or | |
330 | my $public_json_text = $pk->export_key_jwk('public'); | |
331 | ||
332 | Also exports public/private keys as a perl HASH with JWK structure. | |
333 | ||
334 | my $jwk_hash = $pk->export_key_jwk('private', 1); | |
335 | #or | |
336 | my $jwk_hash = $pk->export_key_jwk('public', 1); | |
337 | ||
338 | B<BEWARE:> For JWK support you need to have L<JSON::PP>, L<JSON::XS> or L<Cpanel::JSON::XS> module. | |
339 | ||
340 | =head2 export_key_raw | |
341 | ||
342 | Export raw public/private key | |
343 | ||
344 | my $private_bytes = $pk->export_key_raw('private'); | |
345 | #or | |
346 | my $public_bytes = $pk->export_key_raw('public'); | |
347 | ||
348 | =head2 shared_secret | |
349 | ||
350 | # Alice having her priv key $pk and Bob's public key $pkb | |
351 | my $pk = Crypt::PK::X25519->new($priv_key_filename); | |
352 | my $pkb = Crypt::PK::X25519->new($pub_key_filename); | |
353 | my $shared_secret = $pk->shared_secret($pkb); | |
354 | ||
355 | # Bob having his priv key $pk and Alice's public key $pka | |
356 | my $pk = Crypt::PK::X25519->new($priv_key_filename); | |
357 | my $pka = Crypt::PK::X25519->new($pub_key_filename); | |
358 | my $shared_secret = $pk->shared_secret($pka); # same value as computed by Alice | |
359 | ||
360 | =head2 is_private | |
361 | ||
362 | my $rv = $pk->is_private; | |
363 | # 1 .. private key loaded | |
364 | # 0 .. public key loaded | |
365 | # undef .. no key loaded | |
366 | ||
367 | =head2 key2hash | |
368 | ||
369 | my $hash = $pk->key2hash; | |
370 | ||
371 | # returns hash like this (or undef if no key loaded): | |
372 | { | |
373 | curve => "x25519", | |
374 | # raw public key as a hexadecimal string | |
375 | pub => "EA7806F721A8570512C8F6EFB4E8D620C49A529E4DF5EAA77DEC646FB1E87E41", | |
376 | # raw private key as a hexadecimal string. undef if key is public only | |
377 | priv => "002F93D10BA5728D8DD8E9527721DABA3261C0BB1BEFDE7B4BBDAC631D454651", | |
378 | } | |
379 | ||
380 | =head1 SEE ALSO | |
381 | ||
382 | =over | |
383 | ||
384 | =item * L<https://en.wikipedia.org/wiki/Curve25519> | |
385 | ||
386 | =item * L<https://tools.ietf.org/html/rfc7748> | |
387 | ||
388 | =back | |
389 | ||
390 | =cut |
1 | 1 | |
2 | 2 | use strict; |
3 | 3 | use warnings; |
4 | our $VERSION = '0.066'; | |
4 | our $VERSION = '0.067'; | |
5 | 5 | |
6 | 6 | use Carp; |
7 | 7 |
1 | 1 | |
2 | 2 | use strict; |
3 | 3 | use warnings; |
4 | our $VERSION = '0.066'; | |
4 | our $VERSION = '0.067'; | |
5 | 5 | |
6 | 6 | use base qw(Crypt::PRNG Exporter); |
7 | 7 | our %EXPORT_TAGS = ( all => [qw(random_bytes random_bytes_hex random_bytes_b64 random_bytes_b64u random_string random_string_from rand irand)] ); |
1 | 1 | |
2 | 2 | use strict; |
3 | 3 | use warnings; |
4 | our $VERSION = '0.066'; | |
4 | our $VERSION = '0.067'; | |
5 | 5 | |
6 | 6 | use base qw(Crypt::PRNG Exporter); |
7 | 7 | our %EXPORT_TAGS = ( all => [qw(random_bytes random_bytes_hex random_bytes_b64 random_bytes_b64u random_string random_string_from rand irand)] ); |
1 | 1 | |
2 | 2 | use strict; |
3 | 3 | use warnings; |
4 | our $VERSION = '0.066'; | |
4 | our $VERSION = '0.067'; | |
5 | 5 | |
6 | 6 | use base qw(Crypt::PRNG Exporter); |
7 | 7 | our %EXPORT_TAGS = ( all => [qw(random_bytes random_bytes_hex random_bytes_b64 random_bytes_b64u random_string random_string_from rand irand)] ); |
1 | 1 | |
2 | 2 | use strict; |
3 | 3 | use warnings; |
4 | our $VERSION = '0.066'; | |
4 | our $VERSION = '0.067'; | |
5 | 5 | |
6 | 6 | use base qw(Crypt::PRNG Exporter); |
7 | 7 | our %EXPORT_TAGS = ( all => [qw(random_bytes random_bytes_hex random_bytes_b64 random_bytes_b64u random_string random_string_from rand irand)] ); |
1 | 1 | |
2 | 2 | use strict; |
3 | 3 | use warnings; |
4 | our $VERSION = '0.066'; | |
4 | our $VERSION = '0.067'; | |
5 | 5 | |
6 | 6 | use base qw(Crypt::PRNG Exporter); |
7 | 7 | our %EXPORT_TAGS = ( all => [qw(random_bytes random_bytes_hex random_bytes_b64 random_bytes_b64u random_string random_string_from rand irand)] ); |
1 | 1 | |
2 | 2 | use strict; |
3 | 3 | use warnings; |
4 | our $VERSION = '0.066'; | |
5 | ||
6 | require Exporter; our @ISA = qw(Exporter); ### use Exporter 'import'; | |
4 | our $VERSION = '0.067'; | |
5 | ||
6 | require Exporter; our @ISA = qw(Exporter); ### use Exporter 5.57 'import'; | |
7 | 7 | our %EXPORT_TAGS = ( all => [qw(random_bytes random_bytes_hex random_bytes_b64 random_bytes_b64u random_string random_string_from rand irand)] ); |
8 | 8 | our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } ); |
9 | 9 | our @EXPORT = qw(); |
1 | 1 | |
2 | 2 | use strict; |
3 | 3 | use warnings; |
4 | our $VERSION = '0.066'; | |
4 | our $VERSION = '0.067'; | |
5 | 5 | |
6 | 6 | use CryptX; |
7 | 7 |
1 | 1 | |
2 | 2 | use strict; |
3 | 3 | use warnings; |
4 | our $VERSION = '0.066'; | |
4 | our $VERSION = '0.067'; | |
5 | 5 | |
6 | 6 | use CryptX; |
7 | 7 |
1 | 1 | |
2 | 2 | use strict; |
3 | 3 | use warnings; |
4 | our $VERSION = '0.066'; | |
4 | our $VERSION = '0.067'; | |
5 | 5 | |
6 | 6 | use CryptX; |
7 | 7 |
1 | 1 | |
2 | 2 | use strict; |
3 | 3 | use warnings; |
4 | our $VERSION = '0.066'; | |
4 | our $VERSION = '0.067'; | |
5 | 5 | |
6 | 6 | use CryptX; |
7 | 7 |
1 | 1 | |
2 | 2 | use strict; |
3 | 3 | use warnings; |
4 | our $VERSION = '0.066'; | |
4 | our $VERSION = '0.067'; | |
5 | 5 | |
6 | 6 | use CryptX; |
7 | 7 |
1 | 1 | |
2 | 2 | use strict; |
3 | 3 | use warnings; |
4 | our $VERSION = '0.066'; | |
4 | our $VERSION = '0.067'; | |
5 | 5 | |
6 | 6 | use CryptX; |
7 | 7 |
1 | 1 | |
2 | 2 | use strict; |
3 | 3 | use warnings ; |
4 | our $VERSION = '0.066'; | |
4 | our $VERSION = '0.067'; | |
5 | 5 | |
6 | 6 | require XSLoader; |
7 | 7 | XSLoader::load('CryptX', $VERSION); |
57 | 57 | |
58 | 58 | =head1 NAME |
59 | 59 | |
60 | CryptX - Cryptographic toolkit (self-contained, no external libraries needed) | |
60 | CryptX - Cryptographic toolkit | |
61 | 61 | |
62 | 62 | =head1 DESCRIPTION |
63 | 63 | |
64 | Cryptography in CryptX is based on L<https://github.com/libtom/libtomcrypt> | |
65 | ||
66 | Available modules: | |
64 | Perl modules providing a cryptography based on L<LibTomCrypt|https://github.com/libtom/libtomcrypt> library. | |
67 | 65 | |
68 | 66 | =over |
69 | 67 | |
109 | 107 | |
110 | 108 | =item * Public key cryptography |
111 | 109 | |
112 | L<Crypt::PK::RSA>, L<Crypt::PK::DSA>, L<Crypt::PK::ECC>, L<Crypt::PK::DH> | |
110 | L<Crypt::PK::RSA>, L<Crypt::PK::DSA>, L<Crypt::PK::ECC>, L<Crypt::PK::DH>, L<Crypt::PK::Ed25519>, L<Crypt::PK::X25519> | |
113 | 111 | |
114 | 112 | =item * Cryptographically secure random number generators - see L<Crypt::PRNG> and related modules |
115 | 113 | |
131 | 129 | |
132 | 130 | =head1 COPYRIGHT |
133 | 131 | |
134 | Copyright (c) 2013+ DCIT, a.s. L<https://www.dcit.cz> / Karel Miko | |
132 | Copyright (c) 2013-2020 DCIT, a.s. L<https://www.dcit.cz> / Karel Miko | |
135 | 133 | |
136 | 134 | =cut |
1 | 1 | |
2 | 2 | use strict; |
3 | 3 | use warnings; |
4 | our $VERSION = '0.066'; | |
4 | our $VERSION = '0.067'; | |
5 | 5 | |
6 | 6 | use CryptX; |
7 | 7 | use Carp; |
118 | 118 | ltc/pk/ecc/ltc_ecc_mulmod.o ltc/pk/ecc/ltc_ecc_mulmod_timing.o ltc/pk/ecc/ltc_ecc_points.o \ |
119 | 119 | ltc/pk/ecc/ltc_ecc_projective_add_point.o ltc/pk/ecc/ltc_ecc_projective_dbl_point.o \ |
120 | 120 | ltc/pk/ecc/ltc_ecc_verify_key.o ltc/pk/ed25519/ed25519_export.o ltc/pk/ed25519/ed25519_import.o \ |
121 | ltc/pk/ed25519/ed25519_import_pkcs8.o ltc/pk/ed25519/ed25519_import_x509.o ltc/pk/ed25519/ed25519_make_key.o \ | |
122 | ltc/pk/ed25519/ed25519_set_key.o ltc/pk/ed25519/ed25519_sign.o ltc/pk/ed25519/ed25519_verify.o \ | |
121 | ltc/pk/ed25519/ed25519_import_pkcs8.o ltc/pk/ed25519/ed25519_import_raw.o ltc/pk/ed25519/ed25519_import_x509.o \ | |
122 | ltc/pk/ed25519/ed25519_make_key.o ltc/pk/ed25519/ed25519_sign.o ltc/pk/ed25519/ed25519_verify.o \ | |
123 | 123 | ltc/pk/pkcs1/pkcs_1_i2osp.o ltc/pk/pkcs1/pkcs_1_mgf1.o ltc/pk/pkcs1/pkcs_1_oaep_decode.o \ |
124 | 124 | ltc/pk/pkcs1/pkcs_1_oaep_encode.o ltc/pk/pkcs1/pkcs_1_os2ip.o ltc/pk/pkcs1/pkcs_1_pss_decode.o \ |
125 | 125 | ltc/pk/pkcs1/pkcs_1_pss_encode.o ltc/pk/pkcs1/pkcs_1_v1_5_decode.o ltc/pk/pkcs1/pkcs_1_v1_5_encode.o \ |
128 | 128 | ltc/pk/rsa/rsa_import_x509.o ltc/pk/rsa/rsa_key.o ltc/pk/rsa/rsa_make_key.o ltc/pk/rsa/rsa_set.o \ |
129 | 129 | ltc/pk/rsa/rsa_sign_hash.o ltc/pk/rsa/rsa_sign_saltlen_get.o ltc/pk/rsa/rsa_verify_hash.o \ |
130 | 130 | ltc/pk/x25519/x25519_export.o ltc/pk/x25519/x25519_import.o ltc/pk/x25519/x25519_import_pkcs8.o \ |
131 | ltc/pk/x25519/x25519_import_x509.o ltc/pk/x25519/x25519_make_key.o ltc/pk/x25519/x25519_set_key.o \ | |
131 | ltc/pk/x25519/x25519_import_raw.o ltc/pk/x25519/x25519_import_x509.o ltc/pk/x25519/x25519_make_key.o \ | |
132 | 132 | ltc/pk/x25519/x25519_shared_secret.o ltc/prngs/chacha20.o ltc/prngs/fortuna.o ltc/prngs/rc4.o \ |
133 | 133 | ltc/prngs/rng_get_bytes.o ltc/prngs/rng_make_prng.o ltc/prngs/sober128.o ltc/prngs/sprng.o \ |
134 | 134 | ltc/prngs/yarrow.o ltc/stream/chacha/chacha_crypt.o ltc/stream/chacha/chacha_done.o \ |
125 | 125 | ltc/pk/ecc/ltc_ecc_mulmod.obj ltc/pk/ecc/ltc_ecc_mulmod_timing.obj ltc/pk/ecc/ltc_ecc_points.obj \ |
126 | 126 | ltc/pk/ecc/ltc_ecc_projective_add_point.obj ltc/pk/ecc/ltc_ecc_projective_dbl_point.obj \ |
127 | 127 | ltc/pk/ecc/ltc_ecc_verify_key.obj ltc/pk/ed25519/ed25519_export.obj ltc/pk/ed25519/ed25519_import.obj \ |
128 | ltc/pk/ed25519/ed25519_import_pkcs8.obj ltc/pk/ed25519/ed25519_import_x509.obj ltc/pk/ed25519/ed25519_make_key.obj \ | |
129 | ltc/pk/ed25519/ed25519_set_key.obj ltc/pk/ed25519/ed25519_sign.obj ltc/pk/ed25519/ed25519_verify.obj \ | |
128 | ltc/pk/ed25519/ed25519_import_pkcs8.obj ltc/pk/ed25519/ed25519_import_raw.obj ltc/pk/ed25519/ed25519_import_x509.obj \ | |
129 | ltc/pk/ed25519/ed25519_make_key.obj ltc/pk/ed25519/ed25519_sign.obj ltc/pk/ed25519/ed25519_verify.obj \ | |
130 | 130 | ltc/pk/pkcs1/pkcs_1_i2osp.obj ltc/pk/pkcs1/pkcs_1_mgf1.obj ltc/pk/pkcs1/pkcs_1_oaep_decode.obj \ |
131 | 131 | ltc/pk/pkcs1/pkcs_1_oaep_encode.obj ltc/pk/pkcs1/pkcs_1_os2ip.obj ltc/pk/pkcs1/pkcs_1_pss_decode.obj \ |
132 | 132 | ltc/pk/pkcs1/pkcs_1_pss_encode.obj ltc/pk/pkcs1/pkcs_1_v1_5_decode.obj ltc/pk/pkcs1/pkcs_1_v1_5_encode.obj \ |
135 | 135 | ltc/pk/rsa/rsa_import_pkcs8.obj ltc/pk/rsa/rsa_import_x509.obj ltc/pk/rsa/rsa_key.obj \ |
136 | 136 | ltc/pk/rsa/rsa_make_key.obj ltc/pk/rsa/rsa_set.obj ltc/pk/rsa/rsa_sign_hash.obj ltc/pk/rsa/rsa_sign_saltlen_get.obj \ |
137 | 137 | ltc/pk/rsa/rsa_verify_hash.obj ltc/pk/x25519/x25519_export.obj ltc/pk/x25519/x25519_import.obj \ |
138 | ltc/pk/x25519/x25519_import_pkcs8.obj ltc/pk/x25519/x25519_import_x509.obj ltc/pk/x25519/x25519_make_key.obj \ | |
139 | ltc/pk/x25519/x25519_set_key.obj ltc/pk/x25519/x25519_shared_secret.obj ltc/prngs/chacha20.obj \ | |
138 | ltc/pk/x25519/x25519_import_pkcs8.obj ltc/pk/x25519/x25519_import_raw.obj ltc/pk/x25519/x25519_import_x509.obj \ | |
139 | ltc/pk/x25519/x25519_make_key.obj ltc/pk/x25519/x25519_shared_secret.obj ltc/prngs/chacha20.obj \ | |
140 | 140 | ltc/prngs/fortuna.obj ltc/prngs/rc4.obj ltc/prngs/rng_get_bytes.obj ltc/prngs/rng_make_prng.obj \ |
141 | 141 | ltc/prngs/sober128.obj ltc/prngs/sprng.obj ltc/prngs/yarrow.obj ltc/stream/chacha/chacha_crypt.obj \ |
142 | 142 | ltc/stream/chacha/chacha_done.obj ltc/stream/chacha/chacha_ivctr32.obj ltc/stream/chacha/chacha_ivctr64.obj \ |
10 | 10 | typedef struct Hmac_state { |
11 | 11 | hash_state md; |
12 | 12 | int hash; |
13 | hash_state hashstate; | |
14 | 13 | unsigned char key[MAXBLOCKSIZE]; |
15 | 14 | } hmac_state; |
16 | 15 |
348 | 348 | /** Ed25519 Signature API */ |
349 | 349 | int ed25519_make_key(prng_state *prng, int wprng, curve25519_key *key); |
350 | 350 | |
351 | int ed25519_set_key(const unsigned char *sk, unsigned long sklen, | |
352 | const unsigned char *pk, unsigned long pklen, | |
353 | curve25519_key *key); | |
354 | ||
355 | 351 | int ed25519_export( unsigned char *out, unsigned long *outlen, |
356 | 352 | int which, |
357 | 353 | const curve25519_key *key); |
358 | 354 | |
359 | 355 | int ed25519_import(const unsigned char *in, unsigned long inlen, curve25519_key *key); |
356 | int ed25519_import_raw(const unsigned char *in, unsigned long inlen, int which, curve25519_key *key); | |
360 | 357 | int ed25519_import_x509(const unsigned char *in, unsigned long inlen, curve25519_key *key); |
361 | 358 | int ed25519_import_pkcs8(const unsigned char *in, unsigned long inlen, |
362 | 359 | const void *pwd, unsigned long pwdlen, |
373 | 370 | /** X25519 Key-Exchange API */ |
374 | 371 | int x25519_make_key(prng_state *prng, int wprng, curve25519_key *key); |
375 | 372 | |
376 | int x25519_set_key(const unsigned char *k, unsigned long klen, | |
377 | const unsigned char *u, unsigned long ulen, | |
378 | curve25519_key *key); | |
379 | ||
380 | 373 | int x25519_export( unsigned char *out, unsigned long *outlen, |
381 | 374 | int which, |
382 | 375 | const curve25519_key *key); |
383 | 376 | |
384 | 377 | int x25519_import(const unsigned char *in, unsigned long inlen, curve25519_key *key); |
378 | int x25519_import_raw(const unsigned char *in, unsigned long inlen, int which, curve25519_key *key); | |
385 | 379 | int x25519_import_x509(const unsigned char *in, unsigned long inlen, curve25519_key *key); |
386 | 380 | int x25519_import_pkcs8(const unsigned char *in, unsigned long inlen, |
387 | 381 | const void *pwd, unsigned long pwdlen, |
12 | 12 | #ifdef LTM_DESC |
13 | 13 | |
14 | 14 | #include <tommath.h> |
15 | #if !defined(PRIVATE_MP_WARRAY) && !defined(BN_MP_PRIME_IS_PRIME_C) | |
16 | #include <stdbool.h> | |
17 | #endif | |
15 | 18 | |
16 | 19 | static const struct { |
17 | 20 | mp_err mpi_code; |
446 | 449 | static int isprime(void *a, int b, int *c) |
447 | 450 | { |
448 | 451 | int err; |
452 | #if defined(PRIVATE_MP_WARRAY) || defined(BN_MP_PRIME_IS_PRIME_C) | |
453 | int res; | |
454 | #else | |
455 | bool res; | |
456 | #endif | |
449 | 457 | LTC_ARGCHK(a != NULL); |
450 | 458 | LTC_ARGCHK(c != NULL); |
451 | 459 | b = mp_prime_rabin_miller_trials(mp_count_bits(a)); |
452 | err = mpi_to_ltc_error(mp_prime_is_prime(a, b, c)); | |
453 | *c = (*c == MP_YES) ? LTC_MP_YES : LTC_MP_NO; | |
460 | err = mpi_to_ltc_error(mp_prime_is_prime(a, b, &res)); | |
461 | *c = res ? LTC_MP_YES : LTC_MP_NO; | |
454 | 462 | return err; |
455 | 463 | } |
456 | 464 |
9 | 9 | |
10 | 10 | /** |
11 | 11 | @file ed25519_import.c |
12 | Import a Ed25519 key from a binary packet, Steffen Jaeckel | |
12 | Import a Ed25519 key from a SubjectPublicKeyInfo, Steffen Jaeckel | |
13 | 13 | */ |
14 | 14 | |
15 | 15 | #ifdef LTC_CURVE25519 |
0 | /* LibTomCrypt, modular cryptographic library -- Tom St Denis | |
1 | * | |
2 | * LibTomCrypt is a library that provides various cryptographic | |
3 | * algorithms in a highly modular and flexible manner. | |
4 | * | |
5 | * The library is free for all purposes without any express | |
6 | * guarantee it works. | |
7 | */ | |
8 | #include "tomcrypt_private.h" | |
9 | ||
10 | /** | |
11 | @file ed25519_import_raw.c | |
12 | Set the parameters of an Ed25519 key, Steffen Jaeckel | |
13 | */ | |
14 | ||
15 | #ifdef LTC_CURVE25519 | |
16 | ||
17 | /** | |
18 | Set the parameters of an Ed25519 key | |
19 | ||
20 | @param in The key | |
21 | @param inlen The length of the key | |
22 | @param which Which type of key (PK_PRIVATE or PK_PUBLIC) | |
23 | @param key [out] Destination of the key | |
24 | @return CRYPT_OK if successful | |
25 | */ | |
26 | int ed25519_import_raw(const unsigned char *in, unsigned long inlen, int which, curve25519_key *key) | |
27 | { | |
28 | LTC_ARGCHK(in != NULL); | |
29 | LTC_ARGCHK(inlen == 32uL); | |
30 | LTC_ARGCHK(key != NULL); | |
31 | ||
32 | if (which == PK_PRIVATE) { | |
33 | XMEMCPY(key->priv, in, sizeof(key->priv)); | |
34 | tweetnacl_crypto_sk_to_pk(key->pub, key->priv); | |
35 | } else if (which == PK_PUBLIC) { | |
36 | XMEMCPY(key->pub, in, sizeof(key->pub)); | |
37 | } else { | |
38 | return CRYPT_INVALID_ARG; | |
39 | } | |
40 | key->algo = PKA_ED25519; | |
41 | key->type = which; | |
42 | ||
43 | return CRYPT_OK; | |
44 | } | |
45 | ||
46 | #endif | |
47 | ||
48 | /* ref: $Format:%D$ */ | |
49 | /* git commit: $Format:%H$ */ | |
50 | /* commit time: $Format:%ai$ */ |
0 | /* LibTomCrypt, modular cryptographic library -- Tom St Denis | |
1 | * | |
2 | * LibTomCrypt is a library that provides various cryptographic | |
3 | * algorithms in a highly modular and flexible manner. | |
4 | * | |
5 | * The library is free for all purposes without any express | |
6 | * guarantee it works. | |
7 | */ | |
8 | #include "tomcrypt_private.h" | |
9 | ||
10 | /** | |
11 | @file ed25519_set_ku.c | |
12 | Set the parameters of an Ed25519 key, Steffen Jaeckel | |
13 | */ | |
14 | ||
15 | #ifdef LTC_CURVE25519 | |
16 | ||
17 | /** | |
18 | Set the parameters of an Ed25519 key | |
19 | ||
20 | In case sk and pk are given it is validated that pk is really the | |
21 | corresponding public part of the key pair. | |
22 | ||
23 | @param sk The secret key | |
24 | @param sklen The length of sk | |
25 | @param pk The public key | |
26 | @param pklen The length of pk | |
27 | @param key [out] Destination of the key | |
28 | @return CRYPT_OK if successful | |
29 | */ | |
30 | int ed25519_set_key(const unsigned char *sk, unsigned long sklen, | |
31 | const unsigned char *pk, unsigned long pklen, | |
32 | curve25519_key *key) | |
33 | { | |
34 | LTC_ARGCHK(key != NULL); | |
35 | ||
36 | if (sk != NULL) { | |
37 | LTC_ARGCHK(sklen == 32uL); | |
38 | XMEMCPY(key->priv, sk, sizeof(key->priv)); | |
39 | tweetnacl_crypto_sk_to_pk(key->pub, key->priv); | |
40 | if (pk != NULL) { | |
41 | LTC_ARGCHK(pklen == 32uL); | |
42 | if (XMEM_NEQ(pk, key->pub, sizeof(key->pub)) != 0) { | |
43 | zeromem(key, sizeof(*key)); | |
44 | return CRYPT_INVALID_ARG; | |
45 | } | |
46 | } | |
47 | key->type = PK_PRIVATE; | |
48 | } else if (pk != NULL) { | |
49 | LTC_ARGCHK(pklen == 32uL); | |
50 | XMEMCPY(key->pub, pk, sizeof(key->pub)); | |
51 | key->type = PK_PUBLIC; | |
52 | } else { | |
53 | return CRYPT_INVALID_ARG; | |
54 | } | |
55 | key->algo = PKA_ED25519; | |
56 | ||
57 | return CRYPT_OK; | |
58 | } | |
59 | ||
60 | #endif | |
61 | ||
62 | /* ref: $Format:%D$ */ | |
63 | /* git commit: $Format:%H$ */ | |
64 | /* commit time: $Format:%ai$ */ |
9 | 9 | |
10 | 10 | /** |
11 | 11 | @file x25519_import.c |
12 | Import a X25519 key from a binary packet, Steffen Jaeckel | |
12 | Import a X25519 key from a SubjectPublicKeyInfo, Steffen Jaeckel | |
13 | 13 | */ |
14 | 14 | |
15 | 15 | #ifdef LTC_CURVE25519 |
16 | 16 | |
17 | 17 | /** |
18 | Import a X25519 key from a binary packet | |
18 | Import a X25519 key | |
19 | 19 | @param in The packet to read |
20 | 20 | @param inlen The length of the input packet |
21 | 21 | @param key [out] Where to import the key to |
28 | 28 | |
29 | 29 | LTC_ARGCHK(in != NULL); |
30 | 30 | LTC_ARGCHK(key != NULL); |
31 | ||
32 | /* There's only one case where the inlen is equal to the pubkey-size | |
33 | * and that's a raw pubkey, so let's just do a raw import. | |
34 | */ | |
35 | if (inlen == sizeof(key->pub)) { | |
36 | XMEMCPY(key->pub, in, sizeof(key->pub)); | |
37 | key->type = PK_PUBLIC; | |
38 | key->algo = PKA_X25519; | |
39 | return CRYPT_OK; | |
40 | } | |
41 | 31 | |
42 | 32 | key_len = sizeof(key->pub); |
43 | 33 | if ((err = x509_decode_subject_public_key_info(in, inlen, PKA_X25519, key->pub, &key_len, LTC_ASN1_EOL, NULL, 0uL)) == CRYPT_OK) { |
0 | /* LibTomCrypt, modular cryptographic library -- Tom St Denis | |
1 | * | |
2 | * LibTomCrypt is a library that provides various cryptographic | |
3 | * algorithms in a highly modular and flexible manner. | |
4 | * | |
5 | * The library is free for all purposes without any express | |
6 | * guarantee it works. | |
7 | */ | |
8 | #include "tomcrypt_private.h" | |
9 | ||
10 | /** | |
11 | @file x25519_import_raw.c | |
12 | Set the parameters of a X25519 key, Steffen Jaeckel | |
13 | */ | |
14 | ||
15 | #ifdef LTC_CURVE25519 | |
16 | ||
17 | /** | |
18 | Set the parameters of a X25519 key | |
19 | ||
20 | @param in The key | |
21 | @param inlen The length of the key | |
22 | @param which Which type of key (PK_PRIVATE or PK_PUBLIC) | |
23 | @param key [out] Destination of the key | |
24 | @return CRYPT_OK if successful | |
25 | */ | |
26 | int x25519_import_raw(const unsigned char *in, unsigned long inlen, int which, curve25519_key *key) | |
27 | { | |
28 | LTC_ARGCHK(in != NULL); | |
29 | LTC_ARGCHK(inlen == 32uL); | |
30 | LTC_ARGCHK(key != NULL); | |
31 | ||
32 | if (which == PK_PRIVATE) { | |
33 | XMEMCPY(key->priv, in, sizeof(key->priv)); | |
34 | tweetnacl_crypto_scalarmult_base(key->pub, key->priv); | |
35 | } else if (which == PK_PUBLIC) { | |
36 | XMEMCPY(key->pub, in, sizeof(key->pub)); | |
37 | } else { | |
38 | return CRYPT_INVALID_ARG; | |
39 | } | |
40 | key->algo = PKA_X25519; | |
41 | key->type = which; | |
42 | ||
43 | return CRYPT_OK; | |
44 | } | |
45 | ||
46 | #endif | |
47 | ||
48 | /* ref: $Format:%D$ */ | |
49 | /* git commit: $Format:%H$ */ | |
50 | /* commit time: $Format:%ai$ */ |
0 | /* LibTomCrypt, modular cryptographic library -- Tom St Denis | |
1 | * | |
2 | * LibTomCrypt is a library that provides various cryptographic | |
3 | * algorithms in a highly modular and flexible manner. | |
4 | * | |
5 | * The library is free for all purposes without any express | |
6 | * guarantee it works. | |
7 | */ | |
8 | #include "tomcrypt_private.h" | |
9 | ||
10 | /** | |
11 | @file x25519_set_ku.c | |
12 | Set the parameters of a X25519 key, Steffen Jaeckel | |
13 | */ | |
14 | ||
15 | #ifdef LTC_CURVE25519 | |
16 | ||
17 | /** | |
18 | Set the parameters of a X25519 key | |
19 | ||
20 | In case k and u are given it is validated that u is really the | |
21 | corresponding public part of the key pair | |
22 | ||
23 | @param k The k value (a.k.a scalar or private part) | |
24 | @param klen The length of k | |
25 | @param u The u-coordinate (a.k.a public part) | |
26 | @param ulen The length of u | |
27 | @param key [out] Destination of the key | |
28 | @return CRYPT_OK if successful | |
29 | */ | |
30 | int x25519_set_key(const unsigned char *k, unsigned long klen, | |
31 | const unsigned char *u, unsigned long ulen, | |
32 | curve25519_key *key) | |
33 | { | |
34 | LTC_ARGCHK(key != NULL); | |
35 | ||
36 | if (k != NULL) { | |
37 | LTC_ARGCHK(klen == 32uL); | |
38 | XMEMCPY(key->priv, k, sizeof(key->priv)); | |
39 | tweetnacl_crypto_scalarmult_base(key->pub, key->priv); | |
40 | if (u != NULL) { | |
41 | LTC_ARGCHK(ulen == 32uL); | |
42 | if (XMEM_NEQ(u, key->pub, sizeof(key->pub)) != 0) { | |
43 | zeromem(key, sizeof(*key)); | |
44 | return CRYPT_INVALID_ARG; | |
45 | } | |
46 | } | |
47 | key->type = PK_PRIVATE; | |
48 | } else if (u != NULL) { | |
49 | LTC_ARGCHK(ulen == 32uL); | |
50 | XMEMCPY(key->pub, u, sizeof(key->pub)); | |
51 | key->type = PK_PUBLIC; | |
52 | } else { | |
53 | return CRYPT_INVALID_ARG; | |
54 | } | |
55 | key->algo = PKA_X25519; | |
56 | ||
57 | return CRYPT_OK; | |
58 | } | |
59 | ||
60 | #endif | |
61 | ||
62 | /* ref: $Format:%D$ */ | |
63 | /* git commit: $Format:%H$ */ | |
64 | /* commit time: $Format:%ai$ */ |
100 | 100 | use Crypt::PK::DSA; |
101 | 101 | use Crypt::PK::ECC; |
102 | 102 | use Crypt::PK::RSA; |
103 | use Crypt::PK::X25519; | |
104 | use Crypt::PK::Ed25519; | |
103 | 105 | use Crypt::PK; |
104 | 106 | use Crypt::PRNG::ChaCha20; |
105 | 107 | use Crypt::PRNG::Fortuna; |
5 | 5 | plan skip_all => "set AUTHOR_MODE to enable this test (developer only!)" unless $ENV{AUTHOR_MODE}; |
6 | 6 | plan skip_all => "File::Find not installed" unless eval { require File::Find }; |
7 | 7 | plan skip_all => "Test::Pod not installed" unless eval { require Test::Pod }; |
8 | plan tests => 107; | |
8 | plan tests => 109; | |
9 | 9 | |
10 | 10 | my @files; |
11 | 11 | File::Find::find({ wanted=>sub { push @files, $_ if /\.pm$/ }, no_chdir=>1 }, 'lib'); |
21 | 21 | }, |
22 | 22 | ); |
23 | 23 | |
24 | plan tests => 107; | |
24 | plan tests => 109; | |
25 | 25 | |
26 | 26 | my @files; |
27 | 27 | File::Find::find({ wanted=>sub { push @files, $_ if /\.pm$/ }, no_chdir=>1 }, 'lib'); |
5 | 5 | plan skip_all => "set AUTHOR_MODE to enable this test (developer only!)" unless $ENV{AUTHOR_MODE}; |
6 | 6 | plan skip_all => "Pod::Coverage not installed" unless eval { require Pod::Coverage }; |
7 | 7 | plan skip_all => "File::Find not installed" unless eval { require File::Find }; |
8 | plan tests => 107; | |
8 | plan tests => 109; | |
9 | 9 | |
10 | 10 | my @files; |
11 | 11 | File::Find::find({ wanted=>sub { push @files, $_ if /\.pm$/ }, no_chdir=>1 }, 'lib'); |
0 | openssl genpkey -algorithm x25519 -out openssl_x25519_sk.pem | |
1 | openssl pkey -in openssl_x25519_sk.pem -text | |
2 | openssl pkey -in openssl_x25519_sk.pem -inform PEM -out openssl_x25519_sk.der -outform DER | |
3 | openssl pkey -in openssl_x25519_sk.pem -inform PEM -out openssl_x25519_sk_t.pem -traditional -outform PEM | |
4 | openssl pkey -in openssl_x25519_sk.pem -inform PEM -out openssl_x25519_sk_pw.pem -outform PEM -des -passout pass:secret | |
5 | openssl pkey -in openssl_x25519_sk.pem -inform PEM -out openssl_x25519_sk_pw_t.pem -traditional -outform PEM -des -passout pass:secret | |
6 | openssl pkey -in openssl_x25519_sk.pem -inform PEM -out openssl_x25519_pk.der -pubout -outform DER | |
7 | openssl pkey -in openssl_x25519_sk.pem -inform PEM -out openssl_x25519_pk.pem -pubout -outform PEM | |
8 | openssl pkcs8 -topk8 -inform PEM -outform DER -in openssl_x25519_sk.pem -out openssl_x25519_sk.pkcs8 -nocrypt | |
9 | openssl pkcs8 -topk8 -inform PEM -outform DER -in openssl_x25519_sk.pem -out openssl_x25519_sk_pbes1.pkcs8 -passout pass:secret -v1 PBE-SHA1-3DES | |
10 | openssl pkcs8 -topk8 -inform PEM -outform DER -in openssl_x25519_sk.pem -out openssl_x25519_sk_pbes2.pkcs8 -passout pass:secret -v2 aes256 -v2prf hmacWithSHA512 | |
11 | ||
12 | ||
13 | openssl genpkey -algorithm Ed25519 -out openssl_ed25519_sk.pem | |
14 | openssl pkey -in openssl_ed25519_sk.pem -text | |
15 | openssl pkey -in openssl_ed25519_sk.pem -inform PEM -out openssl_ed25519_sk.der -outform DER | |
16 | openssl pkey -in openssl_ed25519_sk.pem -inform PEM -out openssl_ed25519_sk_t.pem -traditional -outform PEM | |
17 | openssl pkey -in openssl_ed25519_sk.pem -inform PEM -out openssl_ed25519_sk_pw.pem -outform PEM -des -passout pass:secret | |
18 | openssl pkey -in openssl_ed25519_sk.pem -inform PEM -out openssl_ed25519_sk_pw_t.pem -traditional -outform PEM -des -passout pass:secret | |
19 | openssl pkey -in openssl_ed25519_sk.pem -inform PEM -out openssl_ed25519_pk.der -pubout -outform DER | |
20 | openssl pkey -in openssl_ed25519_sk.pem -inform PEM -out openssl_ed25519_pk.pem -pubout -outform PEM | |
21 | openssl pkcs8 -topk8 -inform PEM -outform DER -in openssl_ed25519_sk.pem -out openssl_ed25519_sk.pkcs8 -nocrypt | |
22 | openssl pkcs8 -topk8 -inform PEM -outform DER -in openssl_ed25519_sk.pem -out openssl_ed25519_sk_pbes1.pkcs8 -passout pass:secret -v1 PBE-SHA1-3DES | |
23 | openssl pkcs8 -topk8 -inform PEM -outform DER -in openssl_ed25519_sk.pem -out openssl_ed25519_sk_pbes2.pkcs8 -passout pass:secret -v2 aes256 -v2prf hmacWithSHA512 | |
24 | openssl req -x509 -days 99999 -nodes -subj /CN=CryptX -key openssl_ed25519_sk.pem -out openssl_ed25519_x509.pem | |
25 | openssl x509 -in openssl_ed25519_x509.pem -outform der -out openssl_ed25519_x509.der | |
26 | openssl x509 -in openssl_ed25519_x509.pem -text |
0 | {"kty":"OKP","crv":"Ed25519","x":"oF0a6lgwrJplzfs4RmDUl-NpfEa0Gc8s7IXei9JFRZ0","d":"RcEJum_STotn0j77a5LZnNRX4hNxcsDXSf4rWgwULa0"}⏎ |
0 | {"kty":"OKP","crv":"Ed25519","x":"oF0a6lgwrJplzfs4RmDUl-NpfEa0Gc8s7IXei9JFRZ0"}⏎ |
0 | {"kty":"OKP","crv":"X25519","x":"6ngG9yGoVwUSyPbvtOjWIMSaUp5N9eqnfexkb7HofkE","d":"AC-T0Qulco2N2OlSdyHaujJhwLsb7957S72sYx1FRlE"}⏎ |
0 | {"kty":"OKP","crv":"X25519","x":"6ngG9yGoVwUSyPbvtOjWIMSaUp5N9eqnfexkb7HofkE"}⏎ |
Binary diff not shown
0 | -----BEGIN PUBLIC KEY----- | |
1 | MCowBQYDK2VwAyEAoF0a6lgwrJplzfs4RmDUl+NpfEa0Gc8s7IXei9JFRZ0= | |
2 | -----END PUBLIC KEY----- |
Binary diff not shown
0 | -----BEGIN PRIVATE KEY----- | |
1 | MC4CAQAwBQYDK2VwBCIEIEXBCbpv0k6LZ9I++2uS2ZzUV+ITcXLA10n+K1oMFC2t | |
2 | -----END PRIVATE KEY----- |
Binary diff not shown
Binary diff not shown
Binary diff not shown
0 | -----BEGIN ENCRYPTED PRIVATE KEY----- | |
1 | MIGHMEsGCSqGSIb3DQEFDTA+MCkGCSqGSIb3DQEFDDAcBAjPx9JkdpRH2QICCAAw | |
2 | DAYIKoZIhvcNAgkFADARBgUrDgMCBwQIWWieQojaWTcEOGj43SxqHUys4Eb2M27N | |
3 | AkhqpmhosOxKrpGi0L3h8m8ipHE8EwI94NeOMsjfVw60aJuCrssY5vKN | |
4 | -----END ENCRYPTED PRIVATE KEY----- |
0 | -----BEGIN ED25519 PRIVATE KEY----- | |
1 | Proc-Type: 4,ENCRYPTED | |
2 | DEK-Info: DES-CBC,6A64D756D49C1EFF | |
3 | ||
4 | 8xQ7OyfQ10IITNEKcJGZA53Z1yk+NJQU7hrKqXwChZtgWNInhMBJRl9pozLKDSkH | |
5 | v7u6EOve8NY= | |
6 | -----END ED25519 PRIVATE KEY----- |
0 | -----BEGIN ED25519 PRIVATE KEY----- | |
1 | MC4CAQAwBQYDK2VwBCIEIEXBCbpv0k6LZ9I++2uS2ZzUV+ITcXLA10n+K1oMFC2t | |
2 | -----END ED25519 PRIVATE KEY----- |
Binary diff not shown
0 | -----BEGIN CERTIFICATE----- | |
1 | MIIBODCB66ADAgECAhRWDU9FZBBUZ7KTdX8f7Bco8jsoaTAFBgMrZXAwETEPMA0G | |
2 | A1UEAwwGQ3J5cHRYMCAXDTIwMDExOTEzMDIwMloYDzIyOTMxMTAyMTMwMjAyWjAR | |
3 | MQ8wDQYDVQQDDAZDcnlwdFgwKjAFBgMrZXADIQCgXRrqWDCsmmXN+zhGYNSX42l8 | |
4 | RrQZzyzshd6L0kVFnaNTMFEwHQYDVR0OBBYEFHCGFtVibAxxWYyRt5wazMpqSZDV | |
5 | MB8GA1UdIwQYMBaAFHCGFtVibAxxWYyRt5wazMpqSZDVMA8GA1UdEwEB/wQFMAMB | |
6 | Af8wBQYDK2VwA0EAqG/+98smzqF/wmFX3zHXSaA67as202HnBJod1Tiurw1f+lr3 | |
7 | BX6OMtsDpgRq9O77IF1Qyx/MdJEwwErczOIbAA== | |
8 | -----END CERTIFICATE----- |
Binary diff not shown
0 | -----BEGIN PUBLIC KEY----- | |
1 | MCowBQYDK2VuAyEA6ngG9yGoVwUSyPbvtOjWIMSaUp5N9eqnfexkb7HofkE= | |
2 | -----END PUBLIC KEY----- |
Binary diff not shown
0 | -----BEGIN PRIVATE KEY----- | |
1 | MC4CAQAwBQYDK2VuBCIEIAAvk9ELpXKNjdjpUnch2royYcC7G+/ee0u9rGMdRUZR | |
2 | -----END PRIVATE KEY----- |
Binary diff not shown
Binary diff not shown
Binary diff not shown
0 | -----BEGIN ENCRYPTED PRIVATE KEY----- | |
1 | MIGHMEsGCSqGSIb3DQEFDTA+MCkGCSqGSIb3DQEFDDAcBAiS0NOFZmjJswICCAAw | |
2 | DAYIKoZIhvcNAgkFADARBgUrDgMCBwQIGd40Hdso8Y4EONSRCTrqvftl9hl3zbH9 | |
3 | 2QmHF1KJ4HDMdLDRxD7EynonCw2SV7BO+XNRHzw2yONqiTybfte7nk9t | |
4 | -----END ENCRYPTED PRIVATE KEY----- |
0 | -----BEGIN X25519 PRIVATE KEY----- | |
1 | Proc-Type: 4,ENCRYPTED | |
2 | DEK-Info: DES-CBC,DEEFD3D6B714E75A | |
3 | ||
4 | dfFWP5bKn49aZ993NVAhQQPdFWgsTb4j8CWhRjGBVTPl6ITstAL17deBIRBwZb7h | |
5 | pAyIka81Kfs= | |
6 | -----END X25519 PRIVATE KEY----- |
0 | -----BEGIN X25519 PRIVATE KEY----- | |
1 | MC4CAQAwBQYDK2VuBCIEIAAvk9ELpXKNjdjpUnch2royYcC7G+/ee0u9rGMdRUZR | |
2 | -----END X25519 PRIVATE KEY----- |
0 | -----BEGIN OPENSSH PRIVATE KEY----- | |
1 | b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW | |
2 | QyNTUxOQAAACC9F7IhXEQ6eh6bKGpPDnYogTCYTNlCrMzU8aBku3SfvgAAAJBdUBO/XVAT | |
3 | vwAAAAtzc2gtZWQyNTUxOQAAACC9F7IhXEQ6eh6bKGpPDnYogTCYTNlCrMzU8aBku3Sfvg | |
4 | AAAEDVvPqQHjnRzlV/e2kq+R5egY12xCIw9mJIuVWBm05ZBL0XsiFcRDp6Hpsoak8OdiiB | |
5 | MJhM2UKszNTxoGS7dJ++AAAABkNyeXB0WAECAwQFBgc= | |
6 | -----END OPENSSH PRIVATE KEY----- |
0 | ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIL0XsiFcRDp6Hpsoak8OdiiBMJhM2UKszNTxoGS7dJ++ CryptX |
0 | ---- BEGIN SSH2 PUBLIC KEY ---- | |
1 | Comment: "256-bit ED25519, converted by foo@bar from OpenSSH" | |
2 | AAAAC3NzaC1lZDI1NTE5AAAAIL0XsiFcRDp6Hpsoak8OdiiBMJhM2UKszNTxoGS7dJ++ | |
3 | ---- END SSH2 PUBLIC KEY ---- |
0 | -----BEGIN OPENSSH PRIVATE KEY----- | |
1 | b3BlbnNzaC1rZXktdjEAAAAACmFlczI1Ni1jdHIAAAAGYmNyeXB0AAAAGAAAABDRI/MgFZ | |
2 | zsiclU3RDp2s1hAAAAEAAAAAEAAAAzAAAAC3NzaC1lZDI1NTE5AAAAIL0XsiFcRDp6Hpso | |
3 | ak8OdiiBMJhM2UKszNTxoGS7dJ++AAAAkBCS+qs8+Adk48XS6oNQermt9/wZwSbxP3po6Z | |
4 | 7t14DU4pYTNAMkQglqTHBgdNFpM1badmOXx0UmvIfh4BKBGg4GvJkfJl5WW2jmPnvjJhww | |
5 | l3GBAcYfIVHekEXvfVaLHvo5B5JfAnFlWzEsr+3s1haXVU9eDVVVS2XSrE3O9RD2lbOdwm | |
6 | S599qWbyy3nICJ1w== | |
7 | -----END OPENSSH PRIVATE KEY----- |
0 | use strict; | |
1 | use warnings; | |
2 | use Test::More tests => 91; | |
3 | ||
4 | use Crypt::PK::Ed25519; | |
5 | use Crypt::Misc qw(read_rawfile); | |
6 | ||
7 | { | |
8 | my ($k, $k2); | |
9 | ||
10 | # t/data/openssl_ed25519_sk.pem | |
11 | # ED25519 Private-Key: | |
12 | # priv = 45C109BA6FD24E8B67D23EFB6B92D99CD457E2137172C0D749FE2B5A0C142DAD == RcEJum_STotn0j77a5LZnNRX4hNxcsDXSf4rWgwULa0 | |
13 | # pub = A05D1AEA5830AC9A65CDFB384660D497E3697C46B419CF2CEC85DE8BD245459D == oF0a6lgwrJplzfs4RmDUl-NpfEa0Gc8s7IXei9JFRZ0 | |
14 | ||
15 | my $sk_data = pack("H*", "45C109BA6FD24E8B67D23EFB6B92D99CD457E2137172C0D749FE2B5A0C142DAD"); | |
16 | $k = Crypt::PK::Ed25519->new->import_key_raw($sk_data, 'private'); | |
17 | ok($k, 'new+import_key_raw raw-priv'); | |
18 | ok($k->is_private, 'is_private raw-priv'); | |
19 | is(uc($k->key2hash->{priv}), '45C109BA6FD24E8B67D23EFB6B92D99CD457E2137172C0D749FE2B5A0C142DAD', 'key2hash->{priv} raw-priv'); | |
20 | is(uc($k->key2hash->{pub}), 'A05D1AEA5830AC9A65CDFB384660D497E3697C46B419CF2CEC85DE8BD245459D', 'key2hash->{pub} raw-priv'); | |
21 | is($k->export_key_raw('private'), $sk_data, 'export_key_raw private'); | |
22 | ||
23 | $k2 = Crypt::PK::Ed25519->new->import_key($k->key2hash); | |
24 | ok($k2->is_private, 'is_private raw-priv'); | |
25 | is($k->export_key_der('private'), $k2->export_key_der('private'), 'import_key hash'); | |
26 | ||
27 | my $pk_data = pack("H*", "A05D1AEA5830AC9A65CDFB384660D497E3697C46B419CF2CEC85DE8BD245459D"); | |
28 | $k = Crypt::PK::Ed25519->new->import_key_raw($pk_data, 'public'); | |
29 | ok($k, 'new+import_key_raw raw-pub'); | |
30 | ok(!$k->is_private, '!is_private raw-pub'); | |
31 | is(uc($k->key2hash->{pub}), 'A05D1AEA5830AC9A65CDFB384660D497E3697C46B419CF2CEC85DE8BD245459D', 'key2hash->{pub} raw-pub'); | |
32 | is($k->export_key_raw('public'), $pk_data, 'export_key_raw public'); | |
33 | ||
34 | $k2 = Crypt::PK::Ed25519->new->import_key($k->key2hash); | |
35 | ok(!$k2->is_private, 'is_private raw-priv'); | |
36 | is($k->export_key_der('public'), $k2->export_key_der('public'), 'import_key hash'); | |
37 | ||
38 | my $sk_jwk = { kty=>"OKP",crv=>"Ed25519",d=>"RcEJum_STotn0j77a5LZnNRX4hNxcsDXSf4rWgwULa0",x=>"oF0a6lgwrJplzfs4RmDUl-NpfEa0Gc8s7IXei9JFRZ0" }; | |
39 | $k = Crypt::PK::Ed25519->new($sk_jwk); | |
40 | ok($k, 'new JWKHASH/priv'); | |
41 | ok($k->is_private, 'is_private JWKHASH/priv'); | |
42 | is(uc($k->key2hash->{priv}), '45C109BA6FD24E8B67D23EFB6B92D99CD457E2137172C0D749FE2B5A0C142DAD', 'key2hash->{priv} JWKHASH/priv'); | |
43 | ok(eq_hash($sk_jwk, $k->export_key_jwk('private', 1)), 'JWKHASH export private'); | |
44 | ||
45 | my $pk_jwk = { kty=>"OKP",crv=>"Ed25519",x=>"oF0a6lgwrJplzfs4RmDUl-NpfEa0Gc8s7IXei9JFRZ0" }; | |
46 | $k = Crypt::PK::Ed25519->new($pk_jwk); | |
47 | ok($k, 'new JWKHASH/pub'); | |
48 | ok(!$k->is_private, '!is_private JWKHASH/pub'); | |
49 | is(uc($k->key2hash->{pub}), 'A05D1AEA5830AC9A65CDFB384660D497E3697C46B419CF2CEC85DE8BD245459D', 'key2hash->{pub} JWKHASH/pub'); | |
50 | ok(eq_hash($pk_jwk, $k->export_key_jwk('public', 1)), 'JWKHASH export public'); | |
51 | ||
52 | $k = Crypt::PK::Ed25519->new('t/data/jwk_ed25519-priv1.json'); | |
53 | ok($k, 'new JWK/priv'); | |
54 | ok($k->is_private, 'is_private JWK/priv'); | |
55 | is(uc($k->key2hash->{priv}), '45C109BA6FD24E8B67D23EFB6B92D99CD457E2137172C0D749FE2B5A0C142DAD', 'key2hash->{priv} JWK/priv'); | |
56 | ||
57 | $k = Crypt::PK::Ed25519->new('t/data/jwk_ed25519-pub1.json'); | |
58 | ok($k, 'new JWK/pub'); | |
59 | ok(!$k->is_private, '!is_private JWK/pub'); | |
60 | is(uc($k->key2hash->{pub}), 'A05D1AEA5830AC9A65CDFB384660D497E3697C46B419CF2CEC85DE8BD245459D', 'key2hash->{pub} JWK/pub'); | |
61 | ||
62 | $k = Crypt::PK::Ed25519->new('t/data/openssl_ed25519_sk.der'); | |
63 | ok($k, 'new openssl_ed25519_sk.der'); | |
64 | ok($k->is_private, 'is_private openssl_ed25519_sk.der'); | |
65 | is(uc($k->key2hash->{priv}), '45C109BA6FD24E8B67D23EFB6B92D99CD457E2137172C0D749FE2B5A0C142DAD', 'key2hash->{priv} openssl_ed25519_sk.der'); | |
66 | ||
67 | $k = Crypt::PK::Ed25519->new('t/data/openssl_ed25519_sk.pem'); | |
68 | ok($k, 'new openssl_ed25519_sk.pem'); | |
69 | ok($k->is_private, 'is_private openssl_ed25519_sk.pem'); | |
70 | is(uc($k->key2hash->{priv}), '45C109BA6FD24E8B67D23EFB6B92D99CD457E2137172C0D749FE2B5A0C142DAD', 'key2hash->{priv} openssl_ed25519_sk.pem'); | |
71 | ||
72 | $k = Crypt::PK::Ed25519->new('t/data/openssl_ed25519_sk_t.pem'); | |
73 | ok($k, 'new openssl_ed25519_sk_t.pem'); | |
74 | ok($k->is_private, 'is_private openssl_ed25519_sk_t.pem'); | |
75 | is(uc($k->key2hash->{priv}), '45C109BA6FD24E8B67D23EFB6B92D99CD457E2137172C0D749FE2B5A0C142DAD', 'key2hash->{priv} openssl_ed25519_sk_t.pem'); | |
76 | ||
77 | $k = Crypt::PK::Ed25519->new('t/data/openssl_ed25519_sk.pkcs8'); | |
78 | ok($k, 'new openssl_ed25519_sk.pkcs8'); | |
79 | ok($k->is_private, 'is_private openssl_ed25519_sk.pkcs8'); | |
80 | is(uc($k->key2hash->{priv}), '45C109BA6FD24E8B67D23EFB6B92D99CD457E2137172C0D749FE2B5A0C142DAD', 'key2hash->{priv} openssl_ed25519_sk.pkcs8'); | |
81 | ||
82 | $k = Crypt::PK::Ed25519->new('t/data/openssl_ed25519_sk_pbes1.pkcs8', 'secret'); | |
83 | ok($k, 'new openssl_ed25519_sk_pbes1.pkcs8'); | |
84 | ok($k->is_private, 'is_private openssl_ed25519_sk_pbes1.pkcs8'); | |
85 | is(uc($k->key2hash->{priv}), '45C109BA6FD24E8B67D23EFB6B92D99CD457E2137172C0D749FE2B5A0C142DAD', 'key2hash->{priv} openssl_ed25519_sk_pbes1.pkcs8'); | |
86 | ||
87 | $k = Crypt::PK::Ed25519->new('t/data/openssl_ed25519_sk_pbes2.pkcs8', 'secret'); | |
88 | ok($k, 'new openssl_ed25519_sk_pbes2.pkcs8'); | |
89 | ok($k->is_private, 'is_private openssl_ed25519_sk_pbes2.pkcs8'); | |
90 | is(uc($k->key2hash->{priv}), '45C109BA6FD24E8B67D23EFB6B92D99CD457E2137172C0D749FE2B5A0C142DAD', 'key2hash->{priv} openssl_ed25519_sk_pbes2.pkcs8'); | |
91 | ||
92 | $k = Crypt::PK::Ed25519->new('t/data/openssl_ed25519_sk_pw.pem', 'secret'); | |
93 | ok($k, 'new openssl_ed25519_sk_pw.pem'); | |
94 | ok($k->is_private, 'is_private openssl_ed25519_sk_pw.pem'); | |
95 | is(uc($k->key2hash->{priv}), '45C109BA6FD24E8B67D23EFB6B92D99CD457E2137172C0D749FE2B5A0C142DAD', 'key2hash->{priv} openssl_ed25519_sk_pw.pem'); | |
96 | ||
97 | $k = Crypt::PK::Ed25519->new('t/data/openssl_ed25519_sk_pw_t.pem', 'secret'); | |
98 | ok($k, 'new openssl_ed25519_sk_pw_t.pem'); | |
99 | ok($k->is_private, 'is_private openssl_ed25519_sk_pw_t.pem'); | |
100 | is(uc($k->key2hash->{priv}), '45C109BA6FD24E8B67D23EFB6B92D99CD457E2137172C0D749FE2B5A0C142DAD', 'key2hash->{priv} openssl_ed25519_sk_pw_t.pem'); | |
101 | ||
102 | $k = Crypt::PK::Ed25519->new('t/data/openssl_ed25519_pk.pem'); | |
103 | ok($k, 'new openssl_ed25519_pk.pem'); | |
104 | ok(!$k->is_private, '!is_private openssl_ed25519_pk.pem'); | |
105 | is(uc($k->key2hash->{pub}), 'A05D1AEA5830AC9A65CDFB384660D497E3697C46B419CF2CEC85DE8BD245459D', 'key2hash->{pub} openssl_ed25519_pk.pem'); | |
106 | ||
107 | $k = Crypt::PK::Ed25519->new('t/data/openssl_ed25519_x509.pem'); | |
108 | ok($k, 'new openssl_ed25519_x509.pem'); | |
109 | ok(!$k->is_private, '!is_private openssl_ed25519_x509.pem'); | |
110 | is(uc($k->key2hash->{pub}), 'A05D1AEA5830AC9A65CDFB384660D497E3697C46B419CF2CEC85DE8BD245459D', 'key2hash->{pub} openssl_ed25519_x509.pem'); | |
111 | ||
112 | $k = Crypt::PK::Ed25519->new('t/data/openssl_ed25519_x509.der'); | |
113 | ok($k, 'new openssl_ed25519_x509.der'); | |
114 | ok(!$k->is_private, '!is_private openssl_ed25519_x509.der'); | |
115 | is(uc($k->key2hash->{pub}), 'A05D1AEA5830AC9A65CDFB384660D497E3697C46B419CF2CEC85DE8BD245459D', 'key2hash->{pub} openssl_ed25519_x509.der'); | |
116 | ||
117 | $k = Crypt::PK::Ed25519->new('t/data/ssh/ssh_ed25519.pub'); | |
118 | ok($k, 'new ssh_ed25519.pub'); | |
119 | ok(!$k->is_private, '!is_private ssh_ed25519.pub'); | |
120 | is(uc($k->key2hash->{pub}), 'BD17B2215C443A7A1E9B286A4F0E76288130984CD942ACCCD4F1A064BB749FBE', 'key2hash->{pub} ssh_ed25519.pub'); | |
121 | ||
122 | $k = Crypt::PK::Ed25519->new('t/data/ssh/ssh_ed25519.pub.rfc4716'); | |
123 | ok($k, 'new ssh_ed25519.pub.rfc4716'); | |
124 | ok(!$k->is_private, '!is_private ssh_ed25519.pub.rfc4716'); | |
125 | is(uc($k->key2hash->{pub}), 'BD17B2215C443A7A1E9B286A4F0E76288130984CD942ACCCD4F1A064BB749FBE', 'key2hash->{pub} ssh_ed25519.pub.rfc4716'); | |
126 | ||
127 | ### $k = Crypt::PK::Ed25519->new('t/data/ssh/ssh_ed25519.priv'); | |
128 | ### ok($k, 'new ssh_ed25519.priv'); | |
129 | ### ok($k->is_private, 'is_private ssh_ed25519.priv'); | |
130 | ||
131 | ### $k = Crypt::PK::Ed25519->new('t/data/ssh/ssh_ed25519_pw.priv', 'secret'); | |
132 | ### ok($k, 'new ssh_ed25519_pw.priv'); | |
133 | ### ok($k->is_private, 'is_private ssh_ed25519_pw.priv'); | |
134 | } | |
135 | ||
136 | { | |
137 | my $k = Crypt::PK::Ed25519->new; | |
138 | $k->generate_key; | |
139 | ok($k, 'generate_key'); | |
140 | ok($k->is_private, 'is_private'); | |
141 | ok($k->export_key_der('private'), 'export_key_der pri'); | |
142 | ok($k->export_key_der('public'), 'export_key_der pub'); | |
143 | } | |
144 | ||
145 | { | |
146 | for (qw( openssl_ed25519_pk.der openssl_ed25519_pk.pem )) { | |
147 | my $k = Crypt::PK::Ed25519->new("t/data/$_"); | |
148 | is($k->export_key_der('public'), read_rawfile("t/data/$_"), 'export_key_der public') if (substr($_, -3) eq "der"); | |
149 | is($k->export_key_pem('public'), read_rawfile("t/data/$_"), 'export_key_pem public') if (substr($_, -3) eq "pem"); | |
150 | } | |
151 | ||
152 | for (qw( openssl_ed25519_sk.der openssl_ed25519_sk_t.pem )) { | |
153 | my $k = Crypt::PK::Ed25519->new("t/data/$_"); | |
154 | is($k->export_key_der('private'), read_rawfile("t/data/$_"), 'export_key_der private') if (substr($_, -3) eq "der"); | |
155 | is($k->export_key_pem('private'), read_rawfile("t/data/$_"), 'export_key_pem private') if (substr($_, -3) eq "pem"); | |
156 | } | |
157 | } | |
158 | ||
159 | { | |
160 | my $sk = Crypt::PK::Ed25519->new; | |
161 | $sk->import_key('t/data/openssl_ed25519_sk.der'); | |
162 | my $pk = Crypt::PK::Ed25519->new; | |
163 | $pk->import_key('t/data/openssl_ed25519_pk.der'); | |
164 | ||
165 | my $sig = $sk->sign_message("message"); | |
166 | ok(length $sig > 60, 'sign_message ' . length($sig)); | |
167 | ok($pk->verify_message($sig, "message"), 'verify_message'); | |
168 | } | |
169 | ||
170 | # test vectors from RFC 8032 | |
171 | { | |
172 | my @test_vectors = ( | |
173 | { | |
174 | SECRETKEY => "9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60", | |
175 | PUBLICKEY => "d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a", | |
176 | MESSAGE => "", # 0 bytes | |
177 | SIGNATURE => "e5564300c360ac729086e2cc806e828a84877f1eb8e5d974d873e065224901555fb8821590a33bacc61e39701cf9b46bd25bf5f0595bbe24655141438e7a100b", | |
178 | }, | |
179 | { | |
180 | SECRETKEY => "4ccd089b28ff96da9db6c346ec114e0f5b8a319f35aba624da8cf6ed4fb8a6fb", | |
181 | PUBLICKEY => "3d4017c3e843895a92b70aa74d1b7ebc9c982ccf2ec4968cc0cd55f12af4660c", | |
182 | MESSAGE => "72", | |
183 | SIGNATURE => "92a009a9f0d4cab8720e820b5f642540a2b27b5416503f8fb3762223ebdb69da085ac1e43e15996e458f3613d0f11d8c387b2eaeb4302aeeb00d291612bb0c00", | |
184 | }, | |
185 | { | |
186 | SECRETKEY => "c5aa8df43f9f837bedb7442f31dcb7b166d38535076f094b85ce3a2e0b4458f7", | |
187 | PUBLICKEY => "fc51cd8e6218a1a38da47ed00230f0580816ed13ba3303ac5deb911548908025", | |
188 | MESSAGE => "af82", | |
189 | SIGNATURE => "6291d657deec24024827e69c3abe01a30ce548a284743a445e3680d7db5ac3ac18ff9b538d16f290ae67f760984dc6594a7c15e9716ed28dc027beceea1ec40a", | |
190 | }, | |
191 | { | |
192 | SECRETKEY => "f5e5767cf153319517630f226876b86c8160cc583bc013744c6bf255f5cc0ee5", | |
193 | PUBLICKEY => "278117fc144c72340f67d0f2316e8386ceffbf2b2428c9c51fef7c597f1d426e", | |
194 | MESSAGE => "08b8b2b733424243760fe426a4b54908632110a66c2f6591eabd3345e3e4eb98fa6e264bf09efe12ee50f8f54e9f77b1e355f6c50544e23fb1433ddf73be84d8". | |
195 | "79de7c0046dc4996d9e773f4bc9efe5738829adb26c81b37c93a1b270b20329d658675fc6ea534e0810a4432826bf58c941efb65d57a338bbd2e26640f89ffbc". | |
196 | "1a858efcb8550ee3a5e1998bd177e93a7363c344fe6b199ee5d02e82d522c4feba15452f80288a821a579116ec6dad2b3b310da903401aa62100ab5d1a36553e". | |
197 | "06203b33890cc9b832f79ef80560ccb9a39ce767967ed628c6ad573cb116dbefefd75499da96bd68a8a97b928a8bbc103b6621fcde2beca1231d206be6cd9ec7". | |
198 | "aff6f6c94fcd7204ed3455c68c83f4a41da4af2b74ef5c53f1d8ac70bdcb7ed185ce81bd84359d44254d95629e9855a94a7c1958d1f8ada5d0532ed8a5aa3fb2". | |
199 | "d17ba70eb6248e594e1a2297acbbb39d502f1a8c6eb6f1ce22b3de1a1f40cc24554119a831a9aad6079cad88425de6bde1a9187ebb6092cf67bf2b13fd65f270". | |
200 | "88d78b7e883c8759d2c4f5c65adb7553878ad575f9fad878e80a0c9ba63bcbcc2732e69485bbc9c90bfbd62481d9089beccf80cfe2df16a2cf65bd92dd597b07". | |
201 | "07e0917af48bbb75fed413d238f5555a7a569d80c3414a8d0859dc65a46128bab27af87a71314f318c782b23ebfe808b82b0ce26401d2e22f04d83d1255dc51a". | |
202 | "ddd3b75a2b1ae0784504df543af8969be3ea7082ff7fc9888c144da2af58429ec96031dbcad3dad9af0dcbaaaf268cb8fcffead94f3c7ca495e056a9b47acdb7". | |
203 | "51fb73e666c6c655ade8297297d07ad1ba5e43f1bca32301651339e22904cc8c42f58c30c04aafdb038dda0847dd988dcda6f3bfd15c4b4c4525004aa06eeff8". | |
204 | "ca61783aacec57fb3d1f92b0fe2fd1a85f6724517b65e614ad6808d6f6ee34dff7310fdc82aebfd904b01e1dc54b2927094b2db68d6f903b68401adebf5a7e08". | |
205 | "d78ff4ef5d63653a65040cf9bfd4aca7984a74d37145986780fc0b16ac451649de6188a7dbdf191f64b5fc5e2ab47b57f7f7276cd419c17a3ca8e1b939ae49e4". | |
206 | "88acba6b965610b5480109c8b17b80e1b7b750dfc7598d5d5011fd2dcc5600a32ef5b52a1ecc820e308aa342721aac0943bf6686b64b2579376504ccc493d97e". | |
207 | "6aed3fb0f9cd71a43dd497f01f17c0e2cb3797aa2a2f256656168e6c496afc5fb93246f6b1116398a346f1a641f3b041e989f7914f90cc2c7fff357876e506b5". | |
208 | "0d334ba77c225bc307ba537152f3f1610e4eafe595f6d9d90d11faa933a15ef1369546868a7f3a45a96768d40fd9d03412c091c6315cf4fde7cb68606937380d". | |
209 | "b2eaaa707b4c4185c32eddcdd306705e4dc1ffc872eeee475a64dfac86aba41c0618983f8741c5ef68d3a101e8a3b8cac60c905c15fc910840b94c00a0b9d0", | |
210 | SIGNATURE => "0aab4c900501b3e24d7cdf4663326a3a87df5e4843b2cbdb67cbf6e460fec350aa5371b1508f9f4528ecea23c436d94b5e8fcd4f681e30a6ac00a9704a188a03", | |
211 | }, | |
212 | { | |
213 | SECRETKEY => "833fe62409237b9d62ec77587520911e9a759cec1d19755b7da901b96dca3d42", | |
214 | PUBLICKEY => "ec172b93ad5e563bf4932c70e1245034c35467ef2efd4d64ebf819683467e2bf", | |
215 | MESSAGE => "ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f", | |
216 | SIGNATURE => "dc2a4459e7369633a52b1bf277839a00201009a3efbf3ecb69bea2186c26b58909351fc9ac90b3ecfdfbc7c66431e0303dca179c138ac17ad9bef1177331a704", | |
217 | } | |
218 | ); | |
219 | for my $tv (@test_vectors) { | |
220 | my $sk = pack("H*", $tv->{SECRETKEY}); | |
221 | my $pk = pack("H*", $tv->{PUBLICKEY}); | |
222 | my $msg = pack("H*", $tv->{MESSAGE}); | |
223 | my $sig = pack("H*", $tv->{SIGNATURE}); | |
224 | my $s = Crypt::PK::Ed25519->new->import_key_raw($sk, 'private'); | |
225 | my $p = Crypt::PK::Ed25519->new->import_key_raw($pk, 'public'); | |
226 | my $sigx = $s->sign_message($msg); | |
227 | my $pkx = $s->export_key_raw('public'); | |
228 | is(unpack("H*", $sigx), $tv->{SIGNATURE}, 'sign'); | |
229 | is(unpack("H*", $pkx), $tv->{PUBLICKEY}, 'public key'); | |
230 | ok($p->verify_message($sig, $msg), 'verify'); | |
231 | } | |
232 | } |
0 | use strict; | |
1 | use warnings; | |
2 | use Test::More tests => 69; | |
3 | ||
4 | use Crypt::PK::X25519; | |
5 | use Crypt::Misc qw(read_rawfile); | |
6 | ||
7 | { | |
8 | my ($k, $k2); | |
9 | ||
10 | # t/data/openssl_x25519_sk.pem | |
11 | # X25519 Private-Key: | |
12 | # priv = 002F93D10BA5728D8DD8E9527721DABA3261C0BB1BEFDE7B4BBDAC631D454651 == AC-T0Qulco2N2OlSdyHaujJhwLsb7957S72sYx1FRlE | |
13 | # pub = EA7806F721A8570512C8F6EFB4E8D620C49A529E4DF5EAA77DEC646FB1E87E41 == 6ngG9yGoVwUSyPbvtOjWIMSaUp5N9eqnfexkb7HofkE | |
14 | ||
15 | my $sk_data = pack("H*", "002F93D10BA5728D8DD8E9527721DABA3261C0BB1BEFDE7B4BBDAC631D454651"); | |
16 | $k = Crypt::PK::X25519->new->import_key_raw($sk_data, 'private'); | |
17 | ok($k, 'new+import_key_raw raw-priv'); | |
18 | ok($k->is_private, 'is_private raw-priv'); | |
19 | is(uc($k->key2hash->{priv}), '002F93D10BA5728D8DD8E9527721DABA3261C0BB1BEFDE7B4BBDAC631D454651', 'key2hash->{priv} raw-priv'); | |
20 | is(uc($k->key2hash->{pub}), 'EA7806F721A8570512C8F6EFB4E8D620C49A529E4DF5EAA77DEC646FB1E87E41', 'key2hash->{pub} raw-priv'); | |
21 | is($k->export_key_raw('private'), $sk_data, 'export_key_raw private'); | |
22 | ||
23 | $k2 = Crypt::PK::X25519->new->import_key($k->key2hash); | |
24 | ok($k2->is_private, 'is_private raw-priv'); | |
25 | is($k->export_key_der('private'), $k2->export_key_der('private'), 'import_key hash'); | |
26 | ||
27 | my $pk_data = pack("H*", "EA7806F721A8570512C8F6EFB4E8D620C49A529E4DF5EAA77DEC646FB1E87E41"); | |
28 | $k = Crypt::PK::X25519->new->import_key_raw($pk_data, 'public'); | |
29 | ok($k, 'new+import_key_raw raw-pub'); | |
30 | ok(!$k->is_private, '!is_private raw-pub'); | |
31 | is(uc($k->key2hash->{pub}), 'EA7806F721A8570512C8F6EFB4E8D620C49A529E4DF5EAA77DEC646FB1E87E41', 'key2hash->{pub} raw-pub'); | |
32 | is($k->export_key_raw('public'), $pk_data, 'export_key_raw public'); | |
33 | ||
34 | $k2 = Crypt::PK::X25519->new->import_key($k->key2hash); | |
35 | ok(!$k2->is_private, 'is_private raw-priv'); | |
36 | is($k->export_key_der('public'), $k2->export_key_der('public'), 'import_key hash'); | |
37 | ||
38 | my $sk_jwk = { kty=>"OKP",crv=>"X25519",d=>"AC-T0Qulco2N2OlSdyHaujJhwLsb7957S72sYx1FRlE",x=>"6ngG9yGoVwUSyPbvtOjWIMSaUp5N9eqnfexkb7HofkE" }; | |
39 | $k = Crypt::PK::X25519->new($sk_jwk); | |
40 | ok($k, 'new JWKHASH/priv'); | |
41 | ok($k->is_private, 'is_private JWKHASH/priv'); | |
42 | is(uc($k->key2hash->{priv}), '002F93D10BA5728D8DD8E9527721DABA3261C0BB1BEFDE7B4BBDAC631D454651', 'key2hash->{priv} JWKHASH/priv'); | |
43 | ok(eq_hash($sk_jwk, $k->export_key_jwk('private', 1)), 'JWKHASH export private'); | |
44 | ||
45 | my $pk_jwk = { kty=>"OKP",crv=>"X25519",x=>"6ngG9yGoVwUSyPbvtOjWIMSaUp5N9eqnfexkb7HofkE"}; | |
46 | $k = Crypt::PK::X25519->new($pk_jwk); | |
47 | ok($k, 'new JWKHASH/pub'); | |
48 | ok(!$k->is_private, '!is_private JWKHASH/pub'); | |
49 | is(uc($k->key2hash->{pub}), 'EA7806F721A8570512C8F6EFB4E8D620C49A529E4DF5EAA77DEC646FB1E87E41', 'key2hash->{pub} JWKHASH/pub'); | |
50 | ok(eq_hash($pk_jwk, $k->export_key_jwk('public', 1)), 'JWKHASH export public'); | |
51 | ||
52 | $k = Crypt::PK::X25519->new('t/data/jwk_x25519-priv1.json'); | |
53 | ok($k, 'new JWK/priv'); | |
54 | ok($k->is_private, 'is_private JWK/priv'); | |
55 | is(uc($k->key2hash->{priv}), '002F93D10BA5728D8DD8E9527721DABA3261C0BB1BEFDE7B4BBDAC631D454651', 'key2hash->{priv} JWK/priv'); | |
56 | ||
57 | $k = Crypt::PK::X25519->new('t/data/jwk_x25519-pub1.json'); | |
58 | ok($k, 'new JWK/pub'); | |
59 | ok(!$k->is_private, '!is_private JWK/pub'); | |
60 | is(uc($k->key2hash->{pub}), 'EA7806F721A8570512C8F6EFB4E8D620C49A529E4DF5EAA77DEC646FB1E87E41', 'key2hash->{pub} JWK/pub'); | |
61 | ||
62 | $k = Crypt::PK::X25519->new('t/data/openssl_x25519_sk.der'); | |
63 | ok($k, 'new openssl_x25519_sk.der'); | |
64 | ok($k->is_private, 'is_private openssl_x25519_sk.der'); | |
65 | is(uc($k->key2hash->{priv}), '002F93D10BA5728D8DD8E9527721DABA3261C0BB1BEFDE7B4BBDAC631D454651', 'key2hash->{priv} openssl_x25519_sk.der'); | |
66 | ||
67 | $k = Crypt::PK::X25519->new('t/data/openssl_x25519_sk.pem'); | |
68 | ok($k, 'new openssl_x25519_sk.pem'); | |
69 | ok($k->is_private, 'is_private openssl_x25519_sk.pem'); | |
70 | is(uc($k->key2hash->{priv}), '002F93D10BA5728D8DD8E9527721DABA3261C0BB1BEFDE7B4BBDAC631D454651', 'key2hash->{priv} openssl_x25519_sk.pem'); | |
71 | ||
72 | $k = Crypt::PK::X25519->new('t/data/openssl_x25519_sk_t.pem'); | |
73 | ok($k, 'new openssl_x25519_sk_t.pem'); | |
74 | ok($k->is_private, 'is_private openssl_x25519_sk_t.pem'); | |
75 | is(uc($k->key2hash->{priv}), '002F93D10BA5728D8DD8E9527721DABA3261C0BB1BEFDE7B4BBDAC631D454651', 'key2hash->{priv} openssl_x25519_sk_t.pem'); | |
76 | ||
77 | $k = Crypt::PK::X25519->new('t/data/openssl_x25519_sk.pkcs8'); | |
78 | ok($k, 'new openssl_x25519_sk.pkcs8'); | |
79 | ok($k->is_private, 'is_private openssl_x25519_sk.pkcs8'); | |
80 | is(uc($k->key2hash->{priv}), '002F93D10BA5728D8DD8E9527721DABA3261C0BB1BEFDE7B4BBDAC631D454651', 'key2hash->{priv} openssl_x25519_sk.pkcs8'); | |
81 | ||
82 | $k = Crypt::PK::X25519->new('t/data/openssl_x25519_sk_pbes1.pkcs8', 'secret'); | |
83 | ok($k, 'new openssl_x25519_sk_pbes1.pkcs8'); | |
84 | ok($k->is_private, 'is_private openssl_x25519_sk_pbes1.pkcs8'); | |
85 | is(uc($k->key2hash->{priv}), '002F93D10BA5728D8DD8E9527721DABA3261C0BB1BEFDE7B4BBDAC631D454651', 'key2hash->{priv} openssl_x25519_sk_pbes1.pkcs8'); | |
86 | ||
87 | $k = Crypt::PK::X25519->new('t/data/openssl_x25519_sk_pbes2.pkcs8', 'secret'); | |
88 | ok($k, 'new openssl_x25519_sk_pbes2.pkcs8'); | |
89 | ok($k->is_private, 'is_private openssl_x25519_sk_pbes2.pkcs8'); | |
90 | is(uc($k->key2hash->{priv}), '002F93D10BA5728D8DD8E9527721DABA3261C0BB1BEFDE7B4BBDAC631D454651', 'key2hash->{priv} openssl_x25519_sk_pbes2.pkcs8'); | |
91 | ||
92 | $k = Crypt::PK::X25519->new('t/data/openssl_x25519_sk_pw.pem', 'secret'); | |
93 | ok($k, 'new openssl_x25519_sk_pw.pem'); | |
94 | ok($k->is_private, 'is_private openssl_x25519_sk_pw.pem'); | |
95 | is(uc($k->key2hash->{priv}), '002F93D10BA5728D8DD8E9527721DABA3261C0BB1BEFDE7B4BBDAC631D454651', 'key2hash->{priv} openssl_x25519_sk_pw.pem'); | |
96 | ||
97 | $k = Crypt::PK::X25519->new('t/data/openssl_x25519_sk_pw_t.pem', 'secret'); | |
98 | ok($k, 'new openssl_x25519_sk_pw_t.pem'); | |
99 | ok($k->is_private, 'is_private openssl_x25519_sk_pw_t.pem'); | |
100 | is(uc($k->key2hash->{priv}), '002F93D10BA5728D8DD8E9527721DABA3261C0BB1BEFDE7B4BBDAC631D454651', 'key2hash->{priv} openssl_x25519_sk_pw_t.pem'); | |
101 | ||
102 | $k = Crypt::PK::X25519->new('t/data/openssl_x25519_pk.pem'); | |
103 | ok($k, 'new openssl_x25519_pk.pem'); | |
104 | ok(!$k->is_private, '!is_private openssl_x25519_pk.pem'); | |
105 | is(uc($k->key2hash->{pub}), 'EA7806F721A8570512C8F6EFB4E8D620C49A529E4DF5EAA77DEC646FB1E87E41', 'key2hash->{pub} openssl_x25519_pk.pem'); | |
106 | } | |
107 | ||
108 | { | |
109 | my $k = Crypt::PK::X25519->new; | |
110 | $k->generate_key; | |
111 | ok($k, 'generate_key'); | |
112 | ok($k->is_private, 'is_private'); | |
113 | ok($k->export_key_der('private'), 'export_key_der pri'); | |
114 | ok($k->export_key_der('public'), 'export_key_der pub'); | |
115 | } | |
116 | ||
117 | { | |
118 | for (qw( openssl_x25519_pk.der openssl_x25519_pk.pem )) { | |
119 | my $k = Crypt::PK::X25519->new("t/data/$_"); | |
120 | is($k->export_key_der('public'), read_rawfile("t/data/$_"), 'export_key_der public') if (substr($_, -3) eq "der"); | |
121 | is($k->export_key_pem('public'), read_rawfile("t/data/$_"), 'export_key_pem public') if (substr($_, -3) eq "pem"); | |
122 | } | |
123 | ||
124 | for (qw( openssl_x25519_sk.der openssl_x25519_sk_t.pem )) { | |
125 | my $k = Crypt::PK::X25519->new("t/data/$_"); | |
126 | is($k->export_key_der('private'), read_rawfile("t/data/$_"), 'export_key_der private') if (substr($_, -3) eq "der"); | |
127 | is($k->export_key_pem('private'), read_rawfile("t/data/$_"), 'export_key_pem private') if (substr($_, -3) eq "pem"); | |
128 | } | |
129 | } | |
130 | ||
131 | { | |
132 | my $sk1 = Crypt::PK::X25519->new; | |
133 | $sk1->import_key('t/data/openssl_x25519_sk.der'); | |
134 | my $pk1 = Crypt::PK::X25519->new->import_key_raw($sk1->export_key_raw('public'), 'public'); | |
135 | ok(!$pk1->is_private, '!is_private'); | |
136 | ||
137 | my $sk2 = Crypt::PK::X25519->new; | |
138 | $sk2->generate_key; | |
139 | my $pk2 = Crypt::PK::X25519->new->import_key_raw($sk2->export_key_raw('public'), 'public'); | |
140 | ok(!$pk2->is_private, '!is_private'); | |
141 | ||
142 | my $ss1 = $sk1->shared_secret($pk2); | |
143 | my $ss2 = $sk2->shared_secret($pk1); | |
144 | is(unpack("H*",$ss1), unpack("H*",$ss2), 'shared_secret'); | |
145 | } | |
146 | ||
147 | ||
148 | # rfc7748 test vectors | |
149 | { | |
150 | my $sk = Crypt::PK::X25519->new->import_key_raw(pack("H*", "a546e36bf0527c9d3b16154b82465edd62144c0ac1fc5a18506a2244ba449ac4"), 'private'); | |
151 | my $pk = Crypt::PK::X25519->new->import_key_raw(pack("H*", "e6db6867583030db3594c1a424b15f7c726624ec26b3353b10a903a6d0ab1c4c"), 'public'); | |
152 | is(unpack("H*", $sk->shared_secret($pk)), "c3da55379de9c6908e94ea4df28d084f32eccf03491c71f754b4075577a28552"); | |
153 | } | |
154 | { | |
155 | my $sk = Crypt::PK::X25519->new->import_key_raw(pack("H*", "4b66e9d4d1b4673c5ad22691957d6af5c11b6421e0ea01d42ca4169e7918ba0d"), 'private'); | |
156 | my $pk = Crypt::PK::X25519->new->import_key_raw(pack("H*", "e5210f12786811d3f4b7959d0538ae2c31dbe7106fc03c3efc4cd549c715a493"), 'public'); | |
157 | is(unpack("H*", $sk->shared_secret($pk)), "95cbde9476e8907d7aade45cb4b873f88b595a68799fa152e6f8f7647aac7957"); | |
158 | } | |
159 | { | |
160 | my $sk = Crypt::PK::X25519->new->import_key_raw(pack("H*", "77076d0a7318a57d3c16c17251b26645df4c2f87ebc0992ab177fba51db92c2a"), 'private'); | |
161 | my $pk = Crypt::PK::X25519->new->import_key_raw(pack("H*", "de9edb7d7b7dc1b4d35b61c2ece435373f8343c85b78674dadfc7e146f882b4f"), 'public'); | |
162 | is(unpack("H*", $sk->shared_secret($pk)), "4a5d9d5ba4ce2de1728e3bf480350f25e07e21c947d19e3376f09b3c1e161742"); | |
163 | } | |
164 | { | |
165 | my $sk = Crypt::PK::X25519->new->import_key_raw(pack("H*", "5dab087e624a8a4b79e17f8b83800ee66f3bb1292618b6fd1c2f8b27ff88e0eb"), 'private'); | |
166 | my $pk = Crypt::PK::X25519->new->import_key_raw(pack("H*", "8520f0098930a754748b7ddcb43ef75a0dbf3a0d26381af4eba4a98eaa9b4e6a"), 'public'); | |
167 | is(unpack("H*", $sk->shared_secret($pk)), "4a5d9d5ba4ce2de1728e3bf480350f25e07e21c947d19e3376f09b3c1e161742"); | |
168 | } |