Codebase list libcryptx-perl / ec4052b
New upstream version 0.067 gregor herrmann 4 years ago
167 changed file(s) with 2134 addition(s) and 309 deletion(s). Raw diff Collapse all Expand all
00 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)
16
27 0.066 2019-10-20
38 - fix #57 Build fails on i686
146146 int pindex;
147147 ecc_key key;
148148 } *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;
149163
150164 int mp_tohex_with_leading_zero(mp_int * a, char *str, int maxlen, int minlen) {
151165 int len, rv;
746760 INCLUDE: inc/CryptX_PK_DSA.xs.inc
747761 INCLUDE: inc/CryptX_PK_DH.xs.inc
748762 INCLUDE: inc/CryptX_PK_ECC.xs.inc
763 INCLUDE: inc/CryptX_PK_Ed25519.xs.inc
764 INCLUDE: inc/CryptX_PK_X25519.xs.inc
749765
750766 INCLUDE: inc/CryptX_KeyDerivation.xs.inc
751767
2828 inc/CryptX_PK_DH.xs.inc
2929 inc/CryptX_PK_DSA.xs.inc
3030 inc/CryptX_PK_ECC.xs.inc
31 inc/CryptX_PK_Ed25519.xs.inc
3132 inc/CryptX_PK_RSA.xs.inc
33 inc/CryptX_PK_X25519.xs.inc
3234 inc/CryptX_PRNG.xs.inc
3335 inc/CryptX_Stream_ChaCha.xs.inc
3436 inc/CryptX_Stream_Rabbit.xs.inc
128130 lib/Crypt/PK/DH.pm
129131 lib/Crypt/PK/DSA.pm
130132 lib/Crypt/PK/ECC.pm
133 lib/Crypt/PK/Ed25519.pm
131134 lib/Crypt/PK/RSA.pm
135 lib/Crypt/PK/X25519.pm
132136 lib/Crypt/PRNG.pm
133137 lib/Crypt/PRNG/ChaCha20.pm
134138 lib/Crypt/PRNG/Fortuna.pm
529533 src/ltc/pk/ed25519/ed25519_export.c
530534 src/ltc/pk/ed25519/ed25519_import.c
531535 src/ltc/pk/ed25519/ed25519_import_pkcs8.c
536 src/ltc/pk/ed25519/ed25519_import_raw.c
532537 src/ltc/pk/ed25519/ed25519_import_x509.c
533538 src/ltc/pk/ed25519/ed25519_make_key.c
534 src/ltc/pk/ed25519/ed25519_set_key.c
535539 src/ltc/pk/ed25519/ed25519_sign.c
536540 src/ltc/pk/ed25519/ed25519_verify.c
537541 src/ltc/pk/pkcs1/pkcs_1_i2osp.c
560564 src/ltc/pk/x25519/x25519_export.c
561565 src/ltc/pk/x25519/x25519_import.c
562566 src/ltc/pk/x25519/x25519_import_pkcs8.c
567 src/ltc/pk/x25519/x25519_import_raw.c
563568 src/ltc/pk/x25519/x25519_import_x509.c
564569 src/ltc/pk/x25519/x25519_make_key.c
565 src/ltc/pk/x25519/x25519_set_key.c
566570 src/ltc/pk/x25519/x25519_shared_secret.c
567571 src/ltc/prngs/chacha20.c
568572 src/ltc/prngs/fortuna.c
850854 t/data/ec-des.pem
851855 t/data/ec-des3.pem
852856 t/data/ec-seed.pem
857 t/data/info.txt
853858 t/data/jwk_ec-priv1.json
854859 t/data/jwk_ec-pub.json
855860 t/data/jwk_ec-pub1.json
861 t/data/jwk_ed25519-priv1.json
862 t/data/jwk_ed25519-pub1.json
856863 t/data/jwk_rsa-priv.json
857864 t/data/jwk_rsa-priv1.json
858865 t/data/jwk_rsa-pub1.json
866 t/data/jwk_x25519-priv1.json
867 t/data/jwk_x25519-pub1.json
859868 t/data/openssl_dsa1.der
860869 t/data/openssl_dsa1.pem
861870 t/data/openssl_dsa2.der
873882 t/data/openssl_ec1.pub.pem
874883 t/data/openssl_ec1.pubc.der
875884 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
876897 t/data/openssl_rsa-x509.der
877898 t/data/openssl_rsa-x509.pem
878899 t/data/openssl_rsa1.der
883904 t/data/openssl_rsa2.pem
884905 t/data/openssl_rsa2.pubonly.der
885906 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
886917 t/data/pkcs8.ec-priv-nopass.der
887918 t/data/pkcs8.ec-priv-nopass.pem
888919 t/data/pkcs8.ec-priv-pass.der
920951 t/data/ssh/ssh_ecdsa_521.pub
921952 t/data/ssh/ssh_ecdsa_521.pub.pkcs8
922953 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
923958 t/data/ssh/ssh_rsa_1024
924959 t/data/ssh/ssh_rsa_1024.pub
925960 t/data/ssh/ssh_rsa_1024.pub.pem
10301065 t/pk_dsa_test_vectors_openssl.t
10311066 t/pk_ecc.t
10321067 t/pk_ecc_test_vectors_openssl.t
1068 t/pk_ed25519.t
10331069 t/pk_enc_pem.t
10341070 t/pk_rsa.t
10351071 t/pk_rsa_test_vectors_openssl.t
1072 t/pk_x25519.t
10361073 t/pkcs8.t
10371074 t/prng.t
10381075 t/prng_chacha20.t
00 {
1 "abstract" : "Crypto toolkit",
1 "abstract" : "Cryptographic toolkit",
22 "author" : [
33 "Karel Miko"
44 ],
4444 "url" : "https://github.com/DCIT/perl-CryptX"
4545 }
4646 },
47 "version" : "0.066",
47 "version" : "0.067",
4848 "x_serialization_backend" : "JSON::PP version 2.94"
4949 }
00 ---
1 abstract: 'Crypto toolkit'
1 abstract: 'Cryptographic toolkit'
22 author:
33 - 'Karel Miko'
44 build_requires:
2121 resources:
2222 bugtracker: https://github.com/DCIT/perl-CryptX/issues
2323 repository: https://github.com/DCIT/perl-CryptX
24 version: '0.066'
24 version: '0.067'
2525 x_serialization_backend: 'CPAN::Meta::YAML version 0.018'
6565 NAME => 'CryptX',
6666 VERSION_FROM => 'lib/CryptX.pm',
6767 AUTHOR => 'Karel Miko',
68 ABSTRACT => 'Crypto toolkit',
68 ABSTRACT => 'Cryptographic toolkit',
6969 MIN_PERL_VERSION => '5.006',
7070 LICENSE => 'perl_5',
7171 META_MERGE => { resources => { repository => 'https://github.com/DCIT/perl-CryptX', bugtracker => 'https://github.com/DCIT/perl-CryptX/issues' } },
00 # NAME
11
2 CryptX - Cryptographic toolkit (self-contained, no external libraries needed)
2 CryptX - Cryptographic toolkit
33
44 # DESCRIPTION
55
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.
97
108 - Symmetric ciphers - see [Crypt::Cipher](https://metacpan.org/pod/Crypt::Cipher) and related modules
119
4947
5048 - Public key cryptography
5149
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)
5351
5452 - Cryptographically secure random number generators - see [Crypt::PRNG](https://metacpan.org/pod/Crypt::PRNG) and related modules
5553
6967
7068 # COPYRIGHT
7169
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);
11
22 use strict;
33 use warnings;
4 our $VERSION = '0.066';
4 our $VERSION = '0.067';
55
6 require Exporter; our @ISA = qw(Exporter); ### use Exporter 'import';
6 require Exporter; our @ISA = qw(Exporter); ### use Exporter 5.57 'import';
77 our %EXPORT_TAGS = ( all => [qw( ccm_encrypt_authenticate ccm_decrypt_verify )] );
88 our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
99 our @EXPORT = qw();
11
22 use strict;
33 use warnings;
4 our $VERSION = '0.066';
4 our $VERSION = '0.067';
55
6 require Exporter; our @ISA = qw(Exporter); ### use Exporter 'import';
6 require Exporter; our @ISA = qw(Exporter); ### use Exporter 5.57 'import';
77 our %EXPORT_TAGS = ( all => [qw( chacha20poly1305_encrypt_authenticate chacha20poly1305_decrypt_verify )] );
88 our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
99 our @EXPORT = qw();
11
22 use strict;
33 use warnings;
4 our $VERSION = '0.066';
4 our $VERSION = '0.067';
55
6 require Exporter; our @ISA = qw(Exporter); ### use Exporter 'import';
6 require Exporter; our @ISA = qw(Exporter); ### use Exporter 5.57 'import';
77 our %EXPORT_TAGS = ( all => [qw( eax_encrypt_authenticate eax_decrypt_verify )] );
88 our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
99 our @EXPORT = qw();
11
22 use strict;
33 use warnings;
4 our $VERSION = '0.066';
4 our $VERSION = '0.067';
55
6 require Exporter; our @ISA = qw(Exporter); ### use Exporter 'import';
6 require Exporter; our @ISA = qw(Exporter); ### use Exporter 5.57 'import';
77 our %EXPORT_TAGS = ( all => [qw( gcm_encrypt_authenticate gcm_decrypt_verify )] );
88 our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
99 our @EXPORT = qw();
11
22 use strict;
33 use warnings;
4 our $VERSION = '0.066';
4 our $VERSION = '0.067';
55
6 require Exporter; our @ISA = qw(Exporter); ### use Exporter 'import';
6 require Exporter; our @ISA = qw(Exporter); ### use Exporter 5.57 'import';
77 our %EXPORT_TAGS = ( all => [qw( ocb_encrypt_authenticate ocb_decrypt_verify )] );
88 our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
99 our @EXPORT = qw();
11
22 use strict;
33 use warnings;
4 our $VERSION = '0.066';
4 our $VERSION = '0.067';
55
66 ### not used
77
11
22 use strict;
33 use warnings;
4 our $VERSION = '0.066';
4 our $VERSION = '0.067';
55
66 use base qw(Crypt::Checksum Exporter);
77 our %EXPORT_TAGS = ( all => [qw( adler32_data adler32_data_hex adler32_data_int adler32_file adler32_file_hex adler32_file_int )] );
11
22 use strict;
33 use warnings;
4 our $VERSION = '0.066';
4 our $VERSION = '0.067';
55
66 use base qw(Crypt::Checksum Exporter);
77 our %EXPORT_TAGS = ( all => [qw( crc32_data crc32_data_hex crc32_data_int crc32_file crc32_file_hex crc32_file_int )] );
11
22 use strict;
33 use warnings;
4 our $VERSION = '0.066';
4 our $VERSION = '0.067';
55
6 require Exporter; our @ISA = qw(Exporter); ### use Exporter 'import';
6 require Exporter; our @ISA = qw(Exporter); ### use Exporter 5.57 'import';
77 our %EXPORT_TAGS = ( all => [qw/ adler32_data adler32_data_hex adler32_data_int adler32_file adler32_file_hex adler32_file_int
88 crc32_data crc32_data_hex crc32_data_int crc32_file crc32_file_hex crc32_file_int /] );
99 our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
33
44 use strict;
55 use warnings;
6 our $VERSION = '0.066';
6 our $VERSION = '0.067';
77
88 use base qw(Crypt::Cipher);
99
33
44 use strict;
55 use warnings;
6 our $VERSION = '0.066';
6 our $VERSION = '0.067';
77
88 use base qw(Crypt::Cipher);
99
33
44 use strict;
55 use warnings;
6 our $VERSION = '0.066';
6 our $VERSION = '0.067';
77
88 use base qw(Crypt::Cipher);
99
33
44 use strict;
55 use warnings;
6 our $VERSION = '0.066';
6 our $VERSION = '0.067';
77
88 use base qw(Crypt::Cipher);
99
33
44 use strict;
55 use warnings;
6 our $VERSION = '0.066';
6 our $VERSION = '0.067';
77
88 use base qw(Crypt::Cipher);
99
33
44 use strict;
55 use warnings;
6 our $VERSION = '0.066';
6 our $VERSION = '0.067';
77
88 use base qw(Crypt::Cipher);
99
33
44 use strict;
55 use warnings;
6 our $VERSION = '0.066';
6 our $VERSION = '0.067';
77
88 use base qw(Crypt::Cipher);
99
33
44 use strict;
55 use warnings;
6 our $VERSION = '0.066';
6 our $VERSION = '0.067';
77
88 use base qw(Crypt::Cipher);
99
33
44 use strict;
55 use warnings;
6 our $VERSION = '0.066';
6 our $VERSION = '0.067';
77
88 use base qw(Crypt::Cipher);
99
33
44 use strict;
55 use warnings;
6 our $VERSION = '0.066';
6 our $VERSION = '0.067';
77
88 use base qw(Crypt::Cipher);
99
33
44 use strict;
55 use warnings;
6 our $VERSION = '0.066';
6 our $VERSION = '0.067';
77
88 use base qw(Crypt::Cipher);
99
33
44 use strict;
55 use warnings;
6 our $VERSION = '0.066';
6 our $VERSION = '0.067';
77
88 use base qw(Crypt::Cipher);
99
33
44 use strict;
55 use warnings;
6 our $VERSION = '0.066';
6 our $VERSION = '0.067';
77
88 use base qw(Crypt::Cipher);
99
33
44 use strict;
55 use warnings;
6 our $VERSION = '0.066';
6 our $VERSION = '0.067';
77
88 use base qw(Crypt::Cipher);
99
33
44 use strict;
55 use warnings;
6 our $VERSION = '0.066';
6 our $VERSION = '0.067';
77
88 use base qw(Crypt::Cipher);
99
33
44 use strict;
55 use warnings;
6 our $VERSION = '0.066';
6 our $VERSION = '0.067';
77
88 use base qw(Crypt::Cipher);
99
33
44 use strict;
55 use warnings;
6 our $VERSION = '0.066';
6 our $VERSION = '0.067';
77
88 use base qw(Crypt::Cipher);
99
33
44 use strict;
55 use warnings;
6 our $VERSION = '0.066';
6 our $VERSION = '0.067';
77
88 use base qw(Crypt::Cipher);
99
33
44 use strict;
55 use warnings;
6 our $VERSION = '0.066';
6 our $VERSION = '0.067';
77
88 use base qw(Crypt::Cipher);
99
33
44 use strict;
55 use warnings;
6 our $VERSION = '0.066';
6 our $VERSION = '0.067';
77
88 use base qw(Crypt::Cipher);
99
33
44 use strict;
55 use warnings;
6 our $VERSION = '0.066';
6 our $VERSION = '0.067';
77
88 use base qw(Crypt::Cipher);
99
33
44 use strict;
55 use warnings;
6 our $VERSION = '0.066';
6 our $VERSION = '0.067';
77
88 use base qw(Crypt::Cipher);
99
33
44 use strict;
55 use warnings;
6 our $VERSION = '0.066';
6 our $VERSION = '0.067';
77
88 use base qw(Crypt::Cipher);
99
33
44 use strict;
55 use warnings;
6 our $VERSION = '0.066';
6 our $VERSION = '0.067';
77
88 use base qw(Crypt::Cipher);
99
33
44 use strict;
55 use warnings;
6 our $VERSION = '0.066';
6 our $VERSION = '0.067';
77
88 use base qw(Crypt::Cipher);
99
11
22 use strict;
33 use warnings;
4 our $VERSION = '0.066';
4 our $VERSION = '0.067';
55
66 use Carp;
77 $Carp::Internal{(__PACKAGE__)}++;
33
44 use strict;
55 use warnings;
6 our $VERSION = '0.066';
6 our $VERSION = '0.067';
77
88 use base qw(Crypt::Digest Exporter);
99 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 )] );
33
44 use strict;
55 use warnings;
6 our $VERSION = '0.066';
6 our $VERSION = '0.067';
77
88 use base qw(Crypt::Digest Exporter);
99 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 )] );
33
44 use strict;
55 use warnings;
6 our $VERSION = '0.066';
6 our $VERSION = '0.067';
77
88 use base qw(Crypt::Digest Exporter);
99 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 )] );
33
44 use strict;
55 use warnings;
6 our $VERSION = '0.066';
6 our $VERSION = '0.067';
77
88 use base qw(Crypt::Digest Exporter);
99 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 )] );
33
44 use strict;
55 use warnings;
6 our $VERSION = '0.066';
6 our $VERSION = '0.067';
77
88 use base qw(Crypt::Digest Exporter);
99 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 )] );
33
44 use strict;
55 use warnings;
6 our $VERSION = '0.066';
6 our $VERSION = '0.067';
77
88 use base qw(Crypt::Digest Exporter);
99 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 )] );
33
44 use strict;
55 use warnings;
6 our $VERSION = '0.066';
6 our $VERSION = '0.067';
77
88 use base qw(Crypt::Digest Exporter);
99 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 )] );
33
44 use strict;
55 use warnings;
6 our $VERSION = '0.066';
6 our $VERSION = '0.067';
77
88 use base qw(Crypt::Digest Exporter);
99 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 )] );
33
44 use strict;
55 use warnings;
6 our $VERSION = '0.066';
6 our $VERSION = '0.067';
77
88 use base qw(Crypt::Digest Exporter);
99 our %EXPORT_TAGS = ( all => [qw( chaes chaes_hex chaes_b64 chaes_b64u chaes_file chaes_file_hex chaes_file_b64 chaes_file_b64u )] );
33
44 use strict;
55 use warnings;
6 our $VERSION = '0.066';
6 our $VERSION = '0.067';
77
88 use base qw(Crypt::Digest Exporter);
99 our %EXPORT_TAGS = ( all => [qw( keccak224 keccak224_hex keccak224_b64 keccak224_b64u keccak224_file keccak224_file_hex keccak224_file_b64 keccak224_file_b64u )] );
33
44 use strict;
55 use warnings;
6 our $VERSION = '0.066';
6 our $VERSION = '0.067';
77
88 use base qw(Crypt::Digest Exporter);
99 our %EXPORT_TAGS = ( all => [qw( keccak256 keccak256_hex keccak256_b64 keccak256_b64u keccak256_file keccak256_file_hex keccak256_file_b64 keccak256_file_b64u )] );
33
44 use strict;
55 use warnings;
6 our $VERSION = '0.066';
6 our $VERSION = '0.067';
77
88 use base qw(Crypt::Digest Exporter);
99 our %EXPORT_TAGS = ( all => [qw( keccak384 keccak384_hex keccak384_b64 keccak384_b64u keccak384_file keccak384_file_hex keccak384_file_b64 keccak384_file_b64u )] );
33
44 use strict;
55 use warnings;
6 our $VERSION = '0.066';
6 our $VERSION = '0.067';
77
88 use base qw(Crypt::Digest Exporter);
99 our %EXPORT_TAGS = ( all => [qw( keccak512 keccak512_hex keccak512_b64 keccak512_b64u keccak512_file keccak512_file_hex keccak512_file_b64 keccak512_file_b64u )] );
33
44 use strict;
55 use warnings;
6 our $VERSION = '0.066';
6 our $VERSION = '0.067';
77
88 use base qw(Crypt::Digest Exporter);
99 our %EXPORT_TAGS = ( all => [qw( md2 md2_hex md2_b64 md2_b64u md2_file md2_file_hex md2_file_b64 md2_file_b64u )] );
33
44 use strict;
55 use warnings;
6 our $VERSION = '0.066';
6 our $VERSION = '0.067';
77
88 use base qw(Crypt::Digest Exporter);
99 our %EXPORT_TAGS = ( all => [qw( md4 md4_hex md4_b64 md4_b64u md4_file md4_file_hex md4_file_b64 md4_file_b64u )] );
33
44 use strict;
55 use warnings;
6 our $VERSION = '0.066';
6 our $VERSION = '0.067';
77
88 use base qw(Crypt::Digest Exporter);
99 our %EXPORT_TAGS = ( all => [qw( md5 md5_hex md5_b64 md5_b64u md5_file md5_file_hex md5_file_b64 md5_file_b64u )] );
33
44 use strict;
55 use warnings;
6 our $VERSION = '0.066';
6 our $VERSION = '0.067';
77
88 use base qw(Crypt::Digest Exporter);
99 our %EXPORT_TAGS = ( all => [qw( ripemd128 ripemd128_hex ripemd128_b64 ripemd128_b64u ripemd128_file ripemd128_file_hex ripemd128_file_b64 ripemd128_file_b64u )] );
33
44 use strict;
55 use warnings;
6 our $VERSION = '0.066';
6 our $VERSION = '0.067';
77
88 use base qw(Crypt::Digest Exporter);
99 our %EXPORT_TAGS = ( all => [qw( ripemd160 ripemd160_hex ripemd160_b64 ripemd160_b64u ripemd160_file ripemd160_file_hex ripemd160_file_b64 ripemd160_file_b64u )] );
33
44 use strict;
55 use warnings;
6 our $VERSION = '0.066';
6 our $VERSION = '0.067';
77
88 use base qw(Crypt::Digest Exporter);
99 our %EXPORT_TAGS = ( all => [qw( ripemd256 ripemd256_hex ripemd256_b64 ripemd256_b64u ripemd256_file ripemd256_file_hex ripemd256_file_b64 ripemd256_file_b64u )] );
33
44 use strict;
55 use warnings;
6 our $VERSION = '0.066';
6 our $VERSION = '0.067';
77
88 use base qw(Crypt::Digest Exporter);
99 our %EXPORT_TAGS = ( all => [qw( ripemd320 ripemd320_hex ripemd320_b64 ripemd320_b64u ripemd320_file ripemd320_file_hex ripemd320_file_b64 ripemd320_file_b64u )] );
33
44 use strict;
55 use warnings;
6 our $VERSION = '0.066';
6 our $VERSION = '0.067';
77
88 use base qw(Crypt::Digest Exporter);
99 our %EXPORT_TAGS = ( all => [qw( sha1 sha1_hex sha1_b64 sha1_b64u sha1_file sha1_file_hex sha1_file_b64 sha1_file_b64u )] );
33
44 use strict;
55 use warnings;
6 our $VERSION = '0.066';
6 our $VERSION = '0.067';
77
88 use base qw(Crypt::Digest Exporter);
99 our %EXPORT_TAGS = ( all => [qw( sha224 sha224_hex sha224_b64 sha224_b64u sha224_file sha224_file_hex sha224_file_b64 sha224_file_b64u )] );
33
44 use strict;
55 use warnings;
6 our $VERSION = '0.066';
6 our $VERSION = '0.067';
77
88 use base qw(Crypt::Digest Exporter);
99 our %EXPORT_TAGS = ( all => [qw( sha256 sha256_hex sha256_b64 sha256_b64u sha256_file sha256_file_hex sha256_file_b64 sha256_file_b64u )] );
33
44 use strict;
55 use warnings;
6 our $VERSION = '0.066';
6 our $VERSION = '0.067';
77
88 use base qw(Crypt::Digest Exporter);
99 our %EXPORT_TAGS = ( all => [qw( sha384 sha384_hex sha384_b64 sha384_b64u sha384_file sha384_file_hex sha384_file_b64 sha384_file_b64u )] );
33
44 use strict;
55 use warnings;
6 our $VERSION = '0.066';
6 our $VERSION = '0.067';
77
88 use base qw(Crypt::Digest Exporter);
99 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 )] );
33
44 use strict;
55 use warnings;
6 our $VERSION = '0.066';
6 our $VERSION = '0.067';
77
88 use base qw(Crypt::Digest Exporter);
99 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 )] );
33
44 use strict;
55 use warnings;
6 our $VERSION = '0.066';
6 our $VERSION = '0.067';
77
88 use base qw(Crypt::Digest Exporter);
99 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 )] );
33
44 use strict;
55 use warnings;
6 our $VERSION = '0.066';
6 our $VERSION = '0.067';
77
88 use base qw(Crypt::Digest Exporter);
99 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 )] );
33
44 use strict;
55 use warnings;
6 our $VERSION = '0.066';
6 our $VERSION = '0.067';
77
88 use base qw(Crypt::Digest Exporter);
99 our %EXPORT_TAGS = ( all => [qw( sha512 sha512_hex sha512_b64 sha512_b64u sha512_file sha512_file_hex sha512_file_b64 sha512_file_b64u )] );
33
44 use strict;
55 use warnings;
6 our $VERSION = '0.066';
6 our $VERSION = '0.067';
77
88 use base qw(Crypt::Digest Exporter);
99 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 )] );
33
44 use strict;
55 use warnings;
6 our $VERSION = '0.066';
6 our $VERSION = '0.067';
77
88 use base qw(Crypt::Digest Exporter);
99 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 )] );
11
22 use strict;
33 use warnings;
4 our $VERSION = '0.066';
4 our $VERSION = '0.067';
55
66 use Carp;
77 $Carp::Internal{(__PACKAGE__)}++;
33
44 use strict;
55 use warnings;
6 our $VERSION = '0.066';
6 our $VERSION = '0.067';
77
88 use base qw(Crypt::Digest Exporter);
99 our %EXPORT_TAGS = ( all => [qw( tiger192 tiger192_hex tiger192_b64 tiger192_b64u tiger192_file tiger192_file_hex tiger192_file_b64 tiger192_file_b64u )] );
33
44 use strict;
55 use warnings;
6 our $VERSION = '0.066';
6 our $VERSION = '0.067';
77
88 use base qw(Crypt::Digest Exporter);
99 our %EXPORT_TAGS = ( all => [qw( whirlpool whirlpool_hex whirlpool_b64 whirlpool_b64u whirlpool_file whirlpool_file_hex whirlpool_file_b64 whirlpool_file_b64u )] );
11
22 use strict;
33 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';
77 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 )] );
88 our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
99 our @EXPORT = qw();
11
22 use strict;
33 use warnings;
4 our $VERSION = '0.066';
4 our $VERSION = '0.067';
55
6 require Exporter; our @ISA = qw(Exporter); ### use Exporter 'import';
6 require Exporter; our @ISA = qw(Exporter); ### use Exporter 5.57 'import';
77 our %EXPORT_TAGS = ( all => [qw(pbkdf1 pbkdf2 hkdf hkdf_expand hkdf_extract)] );
88 our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
99 our @EXPORT = qw();
33
44 use strict;
55 use warnings;
6 our $VERSION = '0.066';
6 our $VERSION = '0.067';
77
88 use base qw(Crypt::Mac Exporter);
99 our %EXPORT_TAGS = ( all => [qw( blake2b blake2b_hex blake2b_b64 blake2b_b64u )] );
33
44 use strict;
55 use warnings;
6 our $VERSION = '0.066';
6 our $VERSION = '0.067';
77
88 use base qw(Crypt::Mac Exporter);
99 our %EXPORT_TAGS = ( all => [qw( blake2s blake2s_hex blake2s_b64 blake2s_b64u )] );
33
44 use strict;
55 use warnings;
6 our $VERSION = '0.066';
6 our $VERSION = '0.067';
77
88 use base qw(Crypt::Mac Exporter);
99 our %EXPORT_TAGS = ( all => [qw( f9 f9_hex f9_b64 f9_b64u )] );
33
44 use strict;
55 use warnings;
6 our $VERSION = '0.066';
6 our $VERSION = '0.067';
77
88 use base qw(Crypt::Mac Exporter);
99 our %EXPORT_TAGS = ( all => [qw( hmac hmac_hex hmac_b64 hmac_b64u )] );
33
44 use strict;
55 use warnings;
6 our $VERSION = '0.066';
6 our $VERSION = '0.067';
77
88 use base qw(Crypt::Mac Exporter);
99 our %EXPORT_TAGS = ( all => [qw( omac omac_hex omac_b64 omac_b64u )] );
33
44 use strict;
55 use warnings;
6 our $VERSION = '0.066';
6 our $VERSION = '0.067';
77
88 use base qw(Crypt::Mac Exporter);
99 our %EXPORT_TAGS = ( all => [qw( pmac pmac_hex pmac_b64 pmac_b64u )] );
33
44 use strict;
55 use warnings;
6 our $VERSION = '0.066';
6 our $VERSION = '0.067';
77
88 use base qw(Crypt::Mac Exporter);
99 our %EXPORT_TAGS = ( all => [qw( pelican pelican_hex pelican_b64 pelican_b64u )] );
33
44 use strict;
55 use warnings;
6 our $VERSION = '0.066';
6 our $VERSION = '0.067';
77
88 use base qw(Crypt::Mac Exporter);
99 our %EXPORT_TAGS = ( all => [qw( poly1305 poly1305_hex poly1305_b64 poly1305_b64u )] );
33
44 use strict;
55 use warnings;
6 our $VERSION = '0.066';
6 our $VERSION = '0.067';
77
88 use base qw(Crypt::Mac Exporter);
99 our %EXPORT_TAGS = ( all => [qw( xcbc xcbc_hex xcbc_b64 xcbc_b64u )] );
11
22 use strict;
33 use warnings;
4 our $VERSION = '0.066';
4 our $VERSION = '0.067';
55
66 use Carp;
77 $Carp::Internal{(__PACKAGE__)}++;
11
22 use strict;
33 use warnings;
4 our $VERSION = '0.066';
4 our $VERSION = '0.067';
55
66 require Exporter; our @ISA = qw(Exporter); ### use Exporter 5.57 'import';
77 use Carp 'croak';
33
44 use strict;
55 use warnings;
6 our $VERSION = '0.066';
6 our $VERSION = '0.067';
77
88 use Crypt::Cipher;
99
33
44 use strict;
55 use warnings;
6 our $VERSION = '0.066';
6 our $VERSION = '0.067';
77
88 use Crypt::Cipher;
99
33
44 use strict;
55 use warnings;
6 our $VERSION = '0.066';
6 our $VERSION = '0.067';
77
88 use Crypt::Cipher;
99
33
44 use strict;
55 use warnings;
6 our $VERSION = '0.066';
6 our $VERSION = '0.067';
77
88 use Crypt::Cipher;
99
33
44 use strict;
55 use warnings;
6 our $VERSION = '0.066';
6 our $VERSION = '0.067';
77
88 use Crypt::Cipher;
99
11
22 use strict;
33 use warnings;
4 our $VERSION = '0.066';
4 our $VERSION = '0.067';
55
66 ### not used
77
11
22 use strict;
33 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';
77 our %EXPORT_TAGS = ( all => [qw( dh_shared_secret )] );
88 our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
99 our @EXPORT = qw();
11
22 use strict;
33 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';
77 our %EXPORT_TAGS = ( all => [qw( dsa_encrypt dsa_decrypt dsa_sign_message dsa_verify_message dsa_sign_hash dsa_verify_hash )] );
88 our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
99 our @EXPORT = qw();
11
22 use strict;
33 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';
77 our %EXPORT_TAGS = ( all => [qw( ecc_encrypt ecc_decrypt ecc_sign_message ecc_verify_message ecc_sign_hash ecc_verify_hash ecc_shared_secret )] );
88 our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
99 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
11
22 use strict;
33 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';
77 our %EXPORT_TAGS = ( all => [qw(rsa_encrypt rsa_decrypt rsa_sign_message rsa_verify_message rsa_sign_hash rsa_verify_hash)] );
88 our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
99 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
11
22 use strict;
33 use warnings;
4 our $VERSION = '0.066';
4 our $VERSION = '0.067';
55
66 use Carp;
77
11
22 use strict;
33 use warnings;
4 our $VERSION = '0.066';
4 our $VERSION = '0.067';
55
66 use base qw(Crypt::PRNG Exporter);
77 our %EXPORT_TAGS = ( all => [qw(random_bytes random_bytes_hex random_bytes_b64 random_bytes_b64u random_string random_string_from rand irand)] );
11
22 use strict;
33 use warnings;
4 our $VERSION = '0.066';
4 our $VERSION = '0.067';
55
66 use base qw(Crypt::PRNG Exporter);
77 our %EXPORT_TAGS = ( all => [qw(random_bytes random_bytes_hex random_bytes_b64 random_bytes_b64u random_string random_string_from rand irand)] );
11
22 use strict;
33 use warnings;
4 our $VERSION = '0.066';
4 our $VERSION = '0.067';
55
66 use base qw(Crypt::PRNG Exporter);
77 our %EXPORT_TAGS = ( all => [qw(random_bytes random_bytes_hex random_bytes_b64 random_bytes_b64u random_string random_string_from rand irand)] );
11
22 use strict;
33 use warnings;
4 our $VERSION = '0.066';
4 our $VERSION = '0.067';
55
66 use base qw(Crypt::PRNG Exporter);
77 our %EXPORT_TAGS = ( all => [qw(random_bytes random_bytes_hex random_bytes_b64 random_bytes_b64u random_string random_string_from rand irand)] );
11
22 use strict;
33 use warnings;
4 our $VERSION = '0.066';
4 our $VERSION = '0.067';
55
66 use base qw(Crypt::PRNG Exporter);
77 our %EXPORT_TAGS = ( all => [qw(random_bytes random_bytes_hex random_bytes_b64 random_bytes_b64u random_string random_string_from rand irand)] );
11
22 use strict;
33 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';
77 our %EXPORT_TAGS = ( all => [qw(random_bytes random_bytes_hex random_bytes_b64 random_bytes_b64u random_string random_string_from rand irand)] );
88 our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
99 our @EXPORT = qw();
11
22 use strict;
33 use warnings;
4 our $VERSION = '0.066';
4 our $VERSION = '0.067';
55
66 use CryptX;
77
11
22 use strict;
33 use warnings;
4 our $VERSION = '0.066';
4 our $VERSION = '0.067';
55
66 use CryptX;
77
11
22 use strict;
33 use warnings;
4 our $VERSION = '0.066';
4 our $VERSION = '0.067';
55
66 use CryptX;
77
11
22 use strict;
33 use warnings;
4 our $VERSION = '0.066';
4 our $VERSION = '0.067';
55
66 use CryptX;
77
11
22 use strict;
33 use warnings;
4 our $VERSION = '0.066';
4 our $VERSION = '0.067';
55
66 use CryptX;
77
11
22 use strict;
33 use warnings;
4 our $VERSION = '0.066';
4 our $VERSION = '0.067';
55
66 use CryptX;
77
11
22 use strict;
33 use warnings ;
4 our $VERSION = '0.066';
4 our $VERSION = '0.067';
55
66 require XSLoader;
77 XSLoader::load('CryptX', $VERSION);
5757
5858 =head1 NAME
5959
60 CryptX - Cryptographic toolkit (self-contained, no external libraries needed)
60 CryptX - Cryptographic toolkit
6161
6262 =head1 DESCRIPTION
6363
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.
6765
6866 =over
6967
109107
110108 =item * Public key cryptography
111109
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>
113111
114112 =item * Cryptographically secure random number generators - see L<Crypt::PRNG> and related modules
115113
131129
132130 =head1 COPYRIGHT
133131
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
135133
136134 =cut
11
22 use strict;
33 use warnings;
4 our $VERSION = '0.066';
4 our $VERSION = '0.067';
55
66 use CryptX;
77 use Carp;
118118 ltc/pk/ecc/ltc_ecc_mulmod.o ltc/pk/ecc/ltc_ecc_mulmod_timing.o ltc/pk/ecc/ltc_ecc_points.o \
119119 ltc/pk/ecc/ltc_ecc_projective_add_point.o ltc/pk/ecc/ltc_ecc_projective_dbl_point.o \
120120 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 \
123123 ltc/pk/pkcs1/pkcs_1_i2osp.o ltc/pk/pkcs1/pkcs_1_mgf1.o ltc/pk/pkcs1/pkcs_1_oaep_decode.o \
124124 ltc/pk/pkcs1/pkcs_1_oaep_encode.o ltc/pk/pkcs1/pkcs_1_os2ip.o ltc/pk/pkcs1/pkcs_1_pss_decode.o \
125125 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 \
128128 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 \
129129 ltc/pk/rsa/rsa_sign_hash.o ltc/pk/rsa/rsa_sign_saltlen_get.o ltc/pk/rsa/rsa_verify_hash.o \
130130 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 \
132132 ltc/pk/x25519/x25519_shared_secret.o ltc/prngs/chacha20.o ltc/prngs/fortuna.o ltc/prngs/rc4.o \
133133 ltc/prngs/rng_get_bytes.o ltc/prngs/rng_make_prng.o ltc/prngs/sober128.o ltc/prngs/sprng.o \
134134 ltc/prngs/yarrow.o ltc/stream/chacha/chacha_crypt.o ltc/stream/chacha/chacha_done.o \
125125 ltc/pk/ecc/ltc_ecc_mulmod.obj ltc/pk/ecc/ltc_ecc_mulmod_timing.obj ltc/pk/ecc/ltc_ecc_points.obj \
126126 ltc/pk/ecc/ltc_ecc_projective_add_point.obj ltc/pk/ecc/ltc_ecc_projective_dbl_point.obj \
127127 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 \
130130 ltc/pk/pkcs1/pkcs_1_i2osp.obj ltc/pk/pkcs1/pkcs_1_mgf1.obj ltc/pk/pkcs1/pkcs_1_oaep_decode.obj \
131131 ltc/pk/pkcs1/pkcs_1_oaep_encode.obj ltc/pk/pkcs1/pkcs_1_os2ip.obj ltc/pk/pkcs1/pkcs_1_pss_decode.obj \
132132 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 \
135135 ltc/pk/rsa/rsa_import_pkcs8.obj ltc/pk/rsa/rsa_import_x509.obj ltc/pk/rsa/rsa_key.obj \
136136 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 \
137137 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 \
140140 ltc/prngs/fortuna.obj ltc/prngs/rc4.obj ltc/prngs/rng_get_bytes.obj ltc/prngs/rng_make_prng.obj \
141141 ltc/prngs/sober128.obj ltc/prngs/sprng.obj ltc/prngs/yarrow.obj ltc/stream/chacha/chacha_crypt.obj \
142142 ltc/stream/chacha/chacha_done.obj ltc/stream/chacha/chacha_ivctr32.obj ltc/stream/chacha/chacha_ivctr64.obj \
1010 typedef struct Hmac_state {
1111 hash_state md;
1212 int hash;
13 hash_state hashstate;
1413 unsigned char key[MAXBLOCKSIZE];
1514 } hmac_state;
1615
348348 /** Ed25519 Signature API */
349349 int ed25519_make_key(prng_state *prng, int wprng, curve25519_key *key);
350350
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
355351 int ed25519_export( unsigned char *out, unsigned long *outlen,
356352 int which,
357353 const curve25519_key *key);
358354
359355 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);
360357 int ed25519_import_x509(const unsigned char *in, unsigned long inlen, curve25519_key *key);
361358 int ed25519_import_pkcs8(const unsigned char *in, unsigned long inlen,
362359 const void *pwd, unsigned long pwdlen,
373370 /** X25519 Key-Exchange API */
374371 int x25519_make_key(prng_state *prng, int wprng, curve25519_key *key);
375372
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
380373 int x25519_export( unsigned char *out, unsigned long *outlen,
381374 int which,
382375 const curve25519_key *key);
383376
384377 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);
385379 int x25519_import_x509(const unsigned char *in, unsigned long inlen, curve25519_key *key);
386380 int x25519_import_pkcs8(const unsigned char *in, unsigned long inlen,
387381 const void *pwd, unsigned long pwdlen,
1212 #ifdef LTM_DESC
1313
1414 #include <tommath.h>
15 #if !defined(PRIVATE_MP_WARRAY) && !defined(BN_MP_PRIME_IS_PRIME_C)
16 #include <stdbool.h>
17 #endif
1518
1619 static const struct {
1720 mp_err mpi_code;
446449 static int isprime(void *a, int b, int *c)
447450 {
448451 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
449457 LTC_ARGCHK(a != NULL);
450458 LTC_ARGCHK(c != NULL);
451459 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;
454462 return err;
455463 }
456464
99
1010 /**
1111 @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
1313 */
1414
1515 #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
-65
src/ltc/pk/ed25519/ed25519_set_key.c less more
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$ */
99
1010 /**
1111 @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
1313 */
1414
1515 #ifdef LTC_CURVE25519
1616
1717 /**
18 Import a X25519 key from a binary packet
18 Import a X25519 key
1919 @param in The packet to read
2020 @param inlen The length of the input packet
2121 @param key [out] Where to import the key to
2828
2929 LTC_ARGCHK(in != NULL);
3030 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 }
4131
4232 key_len = sizeof(key->pub);
4333 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
-65
src/ltc/pk/x25519/x25519_set_key.c less more
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$ */
100100 use Crypt::PK::DSA;
101101 use Crypt::PK::ECC;
102102 use Crypt::PK::RSA;
103 use Crypt::PK::X25519;
104 use Crypt::PK::Ed25519;
103105 use Crypt::PK;
104106 use Crypt::PRNG::ChaCha20;
105107 use Crypt::PRNG::Fortuna;
55 plan skip_all => "set AUTHOR_MODE to enable this test (developer only!)" unless $ENV{AUTHOR_MODE};
66 plan skip_all => "File::Find not installed" unless eval { require File::Find };
77 plan skip_all => "Test::Pod not installed" unless eval { require Test::Pod };
8 plan tests => 107;
8 plan tests => 109;
99
1010 my @files;
1111 File::Find::find({ wanted=>sub { push @files, $_ if /\.pm$/ }, no_chdir=>1 }, 'lib');
2121 },
2222 );
2323
24 plan tests => 107;
24 plan tests => 109;
2525
2626 my @files;
2727 File::Find::find({ wanted=>sub { push @files, $_ if /\.pm$/ }, no_chdir=>1 }, 'lib');
55 plan skip_all => "set AUTHOR_MODE to enable this test (developer only!)" unless $ENV{AUTHOR_MODE};
66 plan skip_all => "Pod::Coverage not installed" unless eval { require Pod::Coverage };
77 plan skip_all => "File::Find not installed" unless eval { require File::Find };
8 plan tests => 107;
8 plan tests => 109;
99
1010 my @files;
1111 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"}
0 -----BEGIN PUBLIC KEY-----
1 MCowBQYDK2VwAyEAoF0a6lgwrJplzfs4RmDUl+NpfEa0Gc8s7IXei9JFRZ0=
2 -----END PUBLIC KEY-----
0 -----BEGIN PRIVATE KEY-----
1 MC4CAQAwBQYDK2VwBCIEIEXBCbpv0k6LZ9I++2uS2ZzUV+ITcXLA10n+K1oMFC2t
2 -----END PRIVATE KEY-----
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-----
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-----
0 -----BEGIN PUBLIC KEY-----
1 MCowBQYDK2VuAyEA6ngG9yGoVwUSyPbvtOjWIMSaUp5N9eqnfexkb7HofkE=
2 -----END PUBLIC KEY-----
0 -----BEGIN PRIVATE KEY-----
1 MC4CAQAwBQYDK2VuBCIEIAAvk9ELpXKNjdjpUnch2royYcC7G+/ee0u9rGMdRUZR
2 -----END PRIVATE KEY-----
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 }
4747 Crypt::PK::DSA T_PTROBJ
4848 Crypt::PK::ECC T_PTROBJ
4949 Crypt::PK::DH T_PTROBJ
50 Crypt::PK::Ed25519 T_PTROBJ
51 Crypt::PK::X25519 T_PTROBJ
5052
5153 Math::BigInt::LTM T_PTROBJ
5254