diff --git a/Changes b/Changes index 00afb1b..45fc237 100644 --- a/Changes +++ b/Changes @@ -1,4 +1,9 @@ Changes for CryptX + +0.067 2020-02-01 + - new: Crypt::PK::Ed25519 + - new: Crypt::PK::X25519 + - bundled libtomcrypt update branch:develop (commit:1937f412 2019-11-22) 0.066 2019-10-20 - fix #57 Build fails on i686 diff --git a/CryptX.xs b/CryptX.xs index 0e0bb19..3648693 100644 --- a/CryptX.xs +++ b/CryptX.xs @@ -147,6 +147,20 @@ int pindex; ecc_key key; } *Crypt__PK__ECC; + +typedef struct ed25519_struct { /* used by Crypt::PK::Ed25519 */ + prng_state pstate; + int pindex; + curve25519_key key; + int initialized; +} *Crypt__PK__Ed25519; + +typedef struct x25519_struct { /* used by Crypt::PK::X25519 */ + prng_state pstate; + int pindex; + curve25519_key key; + int initialized; +} *Crypt__PK__X25519; int mp_tohex_with_leading_zero(mp_int * a, char *str, int maxlen, int minlen) { int len, rv; @@ -747,6 +761,8 @@ INCLUDE: inc/CryptX_PK_DSA.xs.inc INCLUDE: inc/CryptX_PK_DH.xs.inc INCLUDE: inc/CryptX_PK_ECC.xs.inc +INCLUDE: inc/CryptX_PK_Ed25519.xs.inc +INCLUDE: inc/CryptX_PK_X25519.xs.inc INCLUDE: inc/CryptX_KeyDerivation.xs.inc diff --git a/MANIFEST b/MANIFEST index 5cc70c5..9fe2940 100644 --- a/MANIFEST +++ b/MANIFEST @@ -29,7 +29,9 @@ inc/CryptX_PK_DH.xs.inc inc/CryptX_PK_DSA.xs.inc inc/CryptX_PK_ECC.xs.inc +inc/CryptX_PK_Ed25519.xs.inc inc/CryptX_PK_RSA.xs.inc +inc/CryptX_PK_X25519.xs.inc inc/CryptX_PRNG.xs.inc inc/CryptX_Stream_ChaCha.xs.inc inc/CryptX_Stream_Rabbit.xs.inc @@ -129,7 +131,9 @@ lib/Crypt/PK/DH.pm lib/Crypt/PK/DSA.pm lib/Crypt/PK/ECC.pm +lib/Crypt/PK/Ed25519.pm lib/Crypt/PK/RSA.pm +lib/Crypt/PK/X25519.pm lib/Crypt/PRNG.pm lib/Crypt/PRNG/ChaCha20.pm lib/Crypt/PRNG/Fortuna.pm @@ -530,9 +534,9 @@ src/ltc/pk/ed25519/ed25519_export.c src/ltc/pk/ed25519/ed25519_import.c src/ltc/pk/ed25519/ed25519_import_pkcs8.c +src/ltc/pk/ed25519/ed25519_import_raw.c src/ltc/pk/ed25519/ed25519_import_x509.c src/ltc/pk/ed25519/ed25519_make_key.c -src/ltc/pk/ed25519/ed25519_set_key.c src/ltc/pk/ed25519/ed25519_sign.c src/ltc/pk/ed25519/ed25519_verify.c src/ltc/pk/pkcs1/pkcs_1_i2osp.c @@ -561,9 +565,9 @@ src/ltc/pk/x25519/x25519_export.c src/ltc/pk/x25519/x25519_import.c src/ltc/pk/x25519/x25519_import_pkcs8.c +src/ltc/pk/x25519/x25519_import_raw.c src/ltc/pk/x25519/x25519_import_x509.c src/ltc/pk/x25519/x25519_make_key.c -src/ltc/pk/x25519/x25519_set_key.c src/ltc/pk/x25519/x25519_shared_secret.c src/ltc/prngs/chacha20.c src/ltc/prngs/fortuna.c @@ -851,12 +855,17 @@ t/data/ec-des.pem t/data/ec-des3.pem t/data/ec-seed.pem +t/data/info.txt t/data/jwk_ec-priv1.json t/data/jwk_ec-pub.json t/data/jwk_ec-pub1.json +t/data/jwk_ed25519-priv1.json +t/data/jwk_ed25519-pub1.json t/data/jwk_rsa-priv.json t/data/jwk_rsa-priv1.json t/data/jwk_rsa-pub1.json +t/data/jwk_x25519-priv1.json +t/data/jwk_x25519-pub1.json t/data/openssl_dsa1.der t/data/openssl_dsa1.pem t/data/openssl_dsa2.der @@ -874,6 +883,18 @@ t/data/openssl_ec1.pub.pem t/data/openssl_ec1.pubc.der t/data/openssl_ec1.pubc.pem +t/data/openssl_ed25519_pk.der +t/data/openssl_ed25519_pk.pem +t/data/openssl_ed25519_sk.der +t/data/openssl_ed25519_sk.pem +t/data/openssl_ed25519_sk.pkcs8 +t/data/openssl_ed25519_sk_pbes1.pkcs8 +t/data/openssl_ed25519_sk_pbes2.pkcs8 +t/data/openssl_ed25519_sk_pw.pem +t/data/openssl_ed25519_sk_pw_t.pem +t/data/openssl_ed25519_sk_t.pem +t/data/openssl_ed25519_x509.der +t/data/openssl_ed25519_x509.pem t/data/openssl_rsa-x509.der t/data/openssl_rsa-x509.pem t/data/openssl_rsa1.der @@ -884,6 +905,16 @@ t/data/openssl_rsa2.pem t/data/openssl_rsa2.pubonly.der t/data/openssl_rsa2.pubonly.pem +t/data/openssl_x25519_pk.der +t/data/openssl_x25519_pk.pem +t/data/openssl_x25519_sk.der +t/data/openssl_x25519_sk.pem +t/data/openssl_x25519_sk.pkcs8 +t/data/openssl_x25519_sk_pbes1.pkcs8 +t/data/openssl_x25519_sk_pbes2.pkcs8 +t/data/openssl_x25519_sk_pw.pem +t/data/openssl_x25519_sk_pw_t.pem +t/data/openssl_x25519_sk_t.pem t/data/pkcs8.ec-priv-nopass.der t/data/pkcs8.ec-priv-nopass.pem t/data/pkcs8.ec-priv-pass.der @@ -921,6 +952,10 @@ t/data/ssh/ssh_ecdsa_521.pub t/data/ssh/ssh_ecdsa_521.pub.pkcs8 t/data/ssh/ssh_ecdsa_521.pub.rfc4716 +t/data/ssh/ssh_ed25519.priv +t/data/ssh/ssh_ed25519.pub +t/data/ssh/ssh_ed25519.pub.rfc4716 +t/data/ssh/ssh_ed25519_pw.priv t/data/ssh/ssh_rsa_1024 t/data/ssh/ssh_rsa_1024.pub t/data/ssh/ssh_rsa_1024.pub.pem @@ -1031,9 +1066,11 @@ t/pk_dsa_test_vectors_openssl.t t/pk_ecc.t t/pk_ecc_test_vectors_openssl.t +t/pk_ed25519.t t/pk_enc_pem.t t/pk_rsa.t t/pk_rsa_test_vectors_openssl.t +t/pk_x25519.t t/pkcs8.t t/prng.t t/prng_chacha20.t diff --git a/META.json b/META.json index 542585f..f249284 100644 --- a/META.json +++ b/META.json @@ -1,5 +1,5 @@ { - "abstract" : "Crypto toolkit", + "abstract" : "Cryptographic toolkit", "author" : [ "Karel Miko" ], @@ -45,6 +45,6 @@ "url" : "https://github.com/DCIT/perl-CryptX" } }, - "version" : "0.066", + "version" : "0.067", "x_serialization_backend" : "JSON::PP version 2.94" } diff --git a/META.yml b/META.yml index e7ff081..405c4a5 100644 --- a/META.yml +++ b/META.yml @@ -1,5 +1,5 @@ --- -abstract: 'Crypto toolkit' +abstract: 'Cryptographic toolkit' author: - 'Karel Miko' build_requires: @@ -22,5 +22,5 @@ resources: bugtracker: https://github.com/DCIT/perl-CryptX/issues repository: https://github.com/DCIT/perl-CryptX -version: '0.066' +version: '0.067' x_serialization_backend: 'CPAN::Meta::YAML version 0.018' diff --git a/Makefile.PL b/Makefile.PL index af0bbe5..5aa9946 100644 --- a/Makefile.PL +++ b/Makefile.PL @@ -66,7 +66,7 @@ NAME => 'CryptX', VERSION_FROM => 'lib/CryptX.pm', AUTHOR => 'Karel Miko', - ABSTRACT => 'Crypto toolkit', + ABSTRACT => 'Cryptographic toolkit', MIN_PERL_VERSION => '5.006', LICENSE => 'perl_5', META_MERGE => { resources => { repository => 'https://github.com/DCIT/perl-CryptX', bugtracker => 'https://github.com/DCIT/perl-CryptX/issues' } }, diff --git a/README.md b/README.md index 65cdc1d..b063334 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,10 @@ # NAME -CryptX - Cryptographic toolkit (self-contained, no external libraries needed) +CryptX - Cryptographic toolkit # DESCRIPTION -Cryptography in CryptX is based on [https://github.com/libtom/libtomcrypt](https://github.com/libtom/libtomcrypt) - -Available modules: +Perl modules providing a cryptography based on [LibTomCrypt](https://github.com/libtom/libtomcrypt) library. - Symmetric ciphers - see [Crypt::Cipher](https://metacpan.org/pod/Crypt::Cipher) and related modules @@ -50,7 +48,7 @@ - Public key cryptography - [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::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) - Cryptographically secure random number generators - see [Crypt::PRNG](https://metacpan.org/pod/Crypt::PRNG) and related modules @@ -70,4 +68,4 @@ # COPYRIGHT -Copyright (c) 2013+ DCIT, a.s. [https://www.dcit.cz](https://www.dcit.cz) / Karel Miko +Copyright (c) 2013-2020 DCIT, a.s. [https://www.dcit.cz](https://www.dcit.cz) / Karel Miko diff --git a/inc/CryptX_PK_Ed25519.xs.inc b/inc/CryptX_PK_Ed25519.xs.inc new file mode 100644 index 0000000..c7a9bee --- /dev/null +++ b/inc/CryptX_PK_Ed25519.xs.inc @@ -0,0 +1,247 @@ +MODULE = CryptX PACKAGE = Crypt::PK::Ed25519 + +PROTOTYPES: DISABLE + +Crypt::PK::Ed25519 +_new(Class) + CODE: + { + int rv; + Newz(0, RETVAL, 1, struct ed25519_struct); + if (!RETVAL) croak("FATAL: Newz failed"); + RETVAL->initialized = 0; + RETVAL->pindex = find_prng("chacha20"); + if (RETVAL->pindex == -1) { + Safefree(RETVAL); + croak("FATAL: find_prng('chacha20') failed"); + } + rv = rng_make_prng(320, RETVAL->pindex, &RETVAL->pstate, NULL); /* 320bits = 40bytes */ + if (rv != CRYPT_OK) { + Safefree(RETVAL); + croak("FATAL: rng_make_prng failed: %s", error_to_string(rv)); + } + } + OUTPUT: + RETVAL + +void +generate_key(Crypt::PK::Ed25519 self) + PPCODE: + { + int rv; + self->initialized = 0; + rv = ed25519_make_key(&self->pstate, self->pindex, &self->key); + if (rv != CRYPT_OK) croak("FATAL: ed25519_make_key failed: %s", error_to_string(rv)); + self->initialized = 1; + XPUSHs(ST(0)); /* return self */ + } + +void +_import(Crypt::PK::Ed25519 self, SV * key_data) + PPCODE: + { + int rv; + unsigned char *data=NULL; + STRLEN data_len=0; + + data = (unsigned char *)SvPVbyte(key_data, data_len); + self->initialized = 0; + rv = ed25519_import(data, (unsigned long)data_len, &self->key); + if (rv != CRYPT_OK) croak("FATAL: ed25519_import failed: %s", error_to_string(rv)); + self->initialized = 1; + XPUSHs(ST(0)); /* return self */ + } + +void +_import_pkcs8(Crypt::PK::Ed25519 self, SV * key_data, SV * passwd) + PPCODE: + { + int rv; + unsigned char *data=NULL, *pwd=NULL; + STRLEN data_len=0, pwd_len=0; + + data = (unsigned char *)SvPVbyte(key_data, data_len); + if (SvOK(passwd)) { + pwd = (unsigned char *)SvPVbyte(passwd, pwd_len); + } + self->initialized = 0; + rv = ed25519_import_pkcs8(data, (unsigned long)data_len, pwd, (unsigned long)pwd_len, &self->key); + if (rv != CRYPT_OK) croak("FATAL: ed25519_import_pkcs8 failed: %s", error_to_string(rv)); + self->initialized = 1; + XPUSHs(ST(0)); /* return self */ + } + +void +_import_x509(Crypt::PK::Ed25519 self, SV * key_data) + PPCODE: + { + int rv; + unsigned char *data=NULL; + STRLEN data_len=0; + + data = (unsigned char *)SvPVbyte(key_data, data_len); + self->initialized = 0; + rv = ed25519_import_x509(data, (unsigned long)data_len, &self->key); + if (rv != CRYPT_OK) croak("FATAL: ed25519_import_x509 failed: %s", error_to_string(rv)); + self->initialized = 1; + XPUSHs(ST(0)); /* return self */ + } + +void +_import_raw(Crypt::PK::Ed25519 self, SV * key, int which) + PPCODE: + { + int rv; + unsigned char *key_data=NULL; + STRLEN key_len=0; + + if (SvOK(key)) { + key_data = (unsigned char *)SvPVbyte(key, key_len); + } + self->initialized = 0; + if (which == 0) { + rv = ed25519_import_raw(key_data, (unsigned long)key_len, PK_PUBLIC, &self->key); + } + else if (which == 1) { + rv = ed25519_import_raw(key_data, (unsigned long)key_len, PK_PRIVATE, &self->key); + } + else { + croak("FATAL: import_raw invalid type '%d'", which); + } + if (rv != CRYPT_OK) croak("FATAL: ed25519_import_raw failed: %s", error_to_string(rv)); + self->initialized = 1; + XPUSHs(ST(0)); /* return self */ + } + +int +is_private(Crypt::PK::Ed25519 self) + CODE: + if (self->initialized == 0) XSRETURN_UNDEF; + RETVAL = (self->key.type == PK_PRIVATE) ? 1 : 0; + OUTPUT: + RETVAL + +SV* +key2hash(Crypt::PK::Ed25519 self) + PREINIT: + HV *rv_hash; + char buf[32 * 2 + 1]; + unsigned long blen; + SV **not_used; + int rv; + CODE: + if (self->initialized == 0) XSRETURN_UNDEF; + rv_hash = newHV(); + /* priv */ + if (self->key.type == PK_PRIVATE) { + blen = sizeof(buf); + rv = base16_encode(self->key.priv, sizeof(self->key.priv), buf, &blen, 0); + if (rv != CRYPT_OK) croak("FATAL: base16_encode failed: %s", error_to_string(rv)); + not_used = hv_store(rv_hash, "priv", 4, newSVpv(buf, blen), 0); + } + else { + not_used = hv_store(rv_hash, "priv", 4, newSVpvn(NULL, 0), 0); /* undef */ + } + /* pub */ + blen = sizeof(buf); + rv = base16_encode(self->key.pub, sizeof(self->key.pub), buf, &blen, 0); + if (rv != CRYPT_OK) croak("FATAL: base16_encode failed: %s", error_to_string(rv)); + not_used = hv_store(rv_hash, "pub", 3, newSVpv(buf, blen), 0); + /* curve */ + not_used = hv_store(rv_hash, "curve", 5, newSVpv("ed25519", 0), 0); + LTC_UNUSED_PARAM(not_used); + RETVAL = newRV_noinc((SV*)rv_hash); + OUTPUT: + RETVAL + +SV* +export_key_der(Crypt::PK::Ed25519 self, char * type) + CODE: + { + int rv; + unsigned char out[4096]; + unsigned long int out_len = sizeof(out); + + RETVAL = newSVpvn(NULL, 0); /* undef */ + if (strnEQ(type, "private", 7)) { + rv = ed25519_export(out, &out_len, PK_PRIVATE|PK_STD, &self->key); + if (rv != CRYPT_OK) croak("FATAL: ed25519_export(PK_PRIVATE|PK_STD) failed: %s", error_to_string(rv)); + RETVAL = newSVpvn((char*)out, out_len); + } + else if (strnEQ(type, "public", 6)) { + rv = ed25519_export(out, &out_len, PK_PUBLIC|PK_STD, &self->key); + if (rv != CRYPT_OK) croak("FATAL: ed25519_export(PK_PUBLIC|PK_STD) failed: %s", error_to_string(rv)); + RETVAL = newSVpvn((char*)out, out_len); + } + else { + croak("FATAL: export_key_der invalid type '%s'", type); + } + } + OUTPUT: + RETVAL + +SV* +export_key_raw(Crypt::PK::Ed25519 self, char * type) + CODE: + { + int rv; + unsigned char out[32]; + unsigned long int out_len = sizeof(out); + + RETVAL = newSVpvn(NULL, 0); /* undef */ + if (strnEQ(type, "private", 7)) { + rv = ed25519_export(out, &out_len, PK_PRIVATE, &self->key); + if (rv != CRYPT_OK) croak("FATAL: ed25519_export(PK_PRIVATE) failed: %s", error_to_string(rv)); + RETVAL = newSVpvn((char*)out, out_len); + } + else if (strnEQ(type, "public", 6)) { + rv = ed25519_export(out, &out_len, PK_PUBLIC, &self->key); + if (rv != CRYPT_OK) croak("FATAL: ed25519_export(PK_PUBLIC) failed: %s", error_to_string(rv)); + RETVAL = newSVpvn((char*)out, out_len); + } + else { + croak("FATAL: export_key_raw invalid type '%s'", type); + } + } + OUTPUT: + RETVAL + +SV * +sign_message(Crypt::PK::Ed25519 self, SV * data) + CODE: + { + int rv; + unsigned char buffer[64], *data_ptr = NULL; + unsigned long buffer_len = 64; + STRLEN data_len = 0; + + data_ptr = (unsigned char *)SvPVbyte(data, data_len); + rv = ed25519_sign(data_ptr, (unsigned long)data_len, buffer, &buffer_len, &self->key); + if (rv != CRYPT_OK) croak("FATAL: ed25519_sign failed: %s", error_to_string(rv)); + RETVAL = newSVpvn((char*)buffer, buffer_len); + } + OUTPUT: + RETVAL + +int +verify_message(Crypt::PK::Ed25519 self, SV * sig, SV * data) + CODE: + { + int rv, stat; + unsigned char *data_ptr = NULL, *sig_ptr = NULL; + STRLEN data_len = 0, sig_len = 0; + + data_ptr = (unsigned char *)SvPVbyte(data, data_len); + sig_ptr = (unsigned char *)SvPVbyte(sig, sig_len); + RETVAL = 0; + stat = 0; + rv = ed25519_verify(data_ptr, (unsigned long)data_len, sig_ptr, (unsigned long)sig_len, &stat, &self->key); + if (rv == CRYPT_OK && stat == 1) RETVAL = 1; + } + OUTPUT: + RETVAL + +void +DESTROY(Crypt::PK::Ed25519 self) + CODE: + Safefree(self); diff --git a/inc/CryptX_PK_X25519.xs.inc b/inc/CryptX_PK_X25519.xs.inc new file mode 100644 index 0000000..9098ed8 --- /dev/null +++ b/inc/CryptX_PK_X25519.xs.inc @@ -0,0 +1,227 @@ +MODULE = CryptX PACKAGE = Crypt::PK::X25519 + +PROTOTYPES: DISABLE + +Crypt::PK::X25519 +_new(Class) + CODE: + { + int rv; + Newz(0, RETVAL, 1, struct x25519_struct); + if (!RETVAL) croak("FATAL: Newz failed"); + RETVAL->initialized = 0; + RETVAL->pindex = find_prng("chacha20"); + if (RETVAL->pindex == -1) { + Safefree(RETVAL); + croak("FATAL: find_prng('chacha20') failed"); + } + rv = rng_make_prng(320, RETVAL->pindex, &RETVAL->pstate, NULL); /* 320bits = 40bytes */ + if (rv != CRYPT_OK) { + Safefree(RETVAL); + croak("FATAL: rng_make_prng failed: %s", error_to_string(rv)); + } + } + OUTPUT: + RETVAL + +void +generate_key(Crypt::PK::X25519 self) + PPCODE: + { + int rv; + self->initialized = 0; + rv = x25519_make_key(&self->pstate, self->pindex, &self->key); + if (rv != CRYPT_OK) croak("FATAL: x25519_make_key failed: %s", error_to_string(rv)); + self->initialized = 1; + XPUSHs(ST(0)); /* return self */ + } + +void +_import(Crypt::PK::X25519 self, SV * key_data) + PPCODE: + { + int rv; + unsigned char *data=NULL; + STRLEN data_len=0; + + data = (unsigned char *)SvPVbyte(key_data, data_len); + self->initialized = 0; + rv = x25519_import(data, (unsigned long)data_len, &self->key); + if (rv != CRYPT_OK) croak("FATAL: x25519_import failed: %s", error_to_string(rv)); + self->initialized = 1; + XPUSHs(ST(0)); /* return self */ + } + +void +_import_pkcs8(Crypt::PK::X25519 self, SV * key_data, SV * passwd) + PPCODE: + { + int rv; + unsigned char *data=NULL, *pwd=NULL; + STRLEN data_len=0, pwd_len=0; + + data = (unsigned char *)SvPVbyte(key_data, data_len); + if (SvOK(passwd)) { + pwd = (unsigned char *)SvPVbyte(passwd, pwd_len); + } + self->initialized = 0; + rv = x25519_import_pkcs8(data, (unsigned long)data_len, pwd, (unsigned long)pwd_len, &self->key); + if (rv != CRYPT_OK) croak("FATAL: x25519_import_pkcs8 failed: %s", error_to_string(rv)); + self->initialized = 1; + XPUSHs(ST(0)); /* return self */ + } + +void +_import_x509(Crypt::PK::X25519 self, SV * key_data) + PPCODE: + { + int rv; + unsigned char *data=NULL; + STRLEN data_len=0; + + data = (unsigned char *)SvPVbyte(key_data, data_len); + self->initialized = 0; + rv = x25519_import_x509(data, (unsigned long)data_len, &self->key); + if (rv != CRYPT_OK) croak("FATAL: x25519_import_x509 failed: %s", error_to_string(rv)); + self->initialized = 1; + XPUSHs(ST(0)); /* return self */ + } + +void +_import_raw(Crypt::PK::X25519 self, SV * key, int which) + PPCODE: + { + int rv; + unsigned char *key_data=NULL; + STRLEN key_len=0; + + if (SvOK(key)) { + key_data = (unsigned char *)SvPVbyte(key, key_len); + } + self->initialized = 0; + if (which == 0) { + rv = x25519_import_raw(key_data, (unsigned long)key_len, PK_PUBLIC, &self->key); + } + else if (which == 1) { + rv = x25519_import_raw(key_data, (unsigned long)key_len, PK_PRIVATE, &self->key); + } + else { + croak("FATAL: import_raw invalid type '%d'", which); + } + if (rv != CRYPT_OK) croak("FATAL: x25519_import_raw failed: %s", error_to_string(rv)); + self->initialized = 1; + XPUSHs(ST(0)); /* return self */ + } + +int +is_private(Crypt::PK::X25519 self) + CODE: + if (self->initialized == 0) XSRETURN_UNDEF; + RETVAL = (self->key.type == PK_PRIVATE) ? 1 : 0; + OUTPUT: + RETVAL + +SV* +key2hash(Crypt::PK::X25519 self) + PREINIT: + HV *rv_hash; + char buf[32 * 2 + 1]; + unsigned long blen; + SV **not_used; + int rv; + CODE: + if (self->initialized == 0) XSRETURN_UNDEF; + rv_hash = newHV(); + /* priv */ + if (self->key.type == PK_PRIVATE) { + blen = sizeof(buf); + rv = base16_encode(self->key.priv, sizeof(self->key.priv), buf, &blen, 0); + if (rv != CRYPT_OK) croak("FATAL: base16_encode failed: %s", error_to_string(rv)); + not_used = hv_store(rv_hash, "priv", 4, newSVpv(buf, blen), 0); + } + else { + not_used = hv_store(rv_hash, "priv", 4, newSVpvn(NULL, 0), 0); /* undef */ + } + /* pub */ + blen = sizeof(buf); + rv = base16_encode(self->key.pub, sizeof(self->key.pub), buf, &blen, 0); + if (rv != CRYPT_OK) croak("FATAL: base16_encode failed: %s", error_to_string(rv)); + not_used = hv_store(rv_hash, "pub", 3, newSVpv(buf, blen), 0); + /* curve */ + not_used = hv_store(rv_hash, "curve", 5, newSVpv("x25519", 0), 0); + LTC_UNUSED_PARAM(not_used); + RETVAL = newRV_noinc((SV*)rv_hash); + OUTPUT: + RETVAL + +SV* +export_key_der(Crypt::PK::X25519 self, char * type) + CODE: + { + int rv; + unsigned char out[4096]; + unsigned long int out_len = sizeof(out); + + RETVAL = newSVpvn(NULL, 0); /* undef */ + if (strnEQ(type, "private", 7)) { + rv = x25519_export(out, &out_len, PK_PRIVATE|PK_STD, &self->key); + if (rv != CRYPT_OK) croak("FATAL: x25519_export(PK_PRIVATE|PK_STD) failed: %s", error_to_string(rv)); + RETVAL = newSVpvn((char*)out, out_len); + } + else if (strnEQ(type, "public", 6)) { + rv = x25519_export(out, &out_len, PK_PUBLIC|PK_STD, &self->key); + if (rv != CRYPT_OK) croak("FATAL: x25519_export(PK_PUBLIC|PK_STD) failed: %s", error_to_string(rv)); + RETVAL = newSVpvn((char*)out, out_len); + } + else { + croak("FATAL: export_key_der invalid type '%s'", type); + } + } + OUTPUT: + RETVAL + +SV* +export_key_raw(Crypt::PK::X25519 self, char * type) + CODE: + { + int rv; + unsigned char out[32]; + unsigned long int out_len = sizeof(out); + + RETVAL = newSVpvn(NULL, 0); /* undef */ + if (strnEQ(type, "private", 7)) { + rv = x25519_export(out, &out_len, PK_PRIVATE, &self->key); + if (rv != CRYPT_OK) croak("FATAL: x25519_export(PK_PRIVATE) failed: %s", error_to_string(rv)); + RETVAL = newSVpvn((char*)out, out_len); + } + else if (strnEQ(type, "public", 6)) { + rv = x25519_export(out, &out_len, PK_PUBLIC, &self->key); + if (rv != CRYPT_OK) croak("FATAL: x25519_export(PK_PUBLIC) failed: %s", error_to_string(rv)); + RETVAL = newSVpvn((char*)out, out_len); + } + else { + croak("FATAL: export_key_raw invalid type '%s'", type); + } + } + OUTPUT: + RETVAL + +SV * +shared_secret(Crypt::PK::X25519 self, Crypt::PK::X25519 pubkey) + CODE: + { + int rv; + unsigned char buffer[1024]; + unsigned long int buffer_len = sizeof(buffer); + + rv = x25519_shared_secret(&self->key, &pubkey->key, buffer, &buffer_len); + if (rv != CRYPT_OK) croak("FATAL: x25519_shared_secret failed: %s", error_to_string(rv)); + RETVAL = newSVpvn((char*)buffer, buffer_len); + } + OUTPUT: + RETVAL + +void +DESTROY(Crypt::PK::X25519 self) + CODE: + Safefree(self); diff --git a/lib/Crypt/AuthEnc/CCM.pm b/lib/Crypt/AuthEnc/CCM.pm index 3000f4d..50a41f0 100644 --- a/lib/Crypt/AuthEnc/CCM.pm +++ b/lib/Crypt/AuthEnc/CCM.pm @@ -2,9 +2,9 @@ use strict; use warnings; -our $VERSION = '0.066'; +our $VERSION = '0.067'; -require Exporter; our @ISA = qw(Exporter); ### use Exporter 'import'; +require Exporter; our @ISA = qw(Exporter); ### use Exporter 5.57 'import'; our %EXPORT_TAGS = ( all => [qw( ccm_encrypt_authenticate ccm_decrypt_verify )] ); our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } ); our @EXPORT = qw(); diff --git a/lib/Crypt/AuthEnc/ChaCha20Poly1305.pm b/lib/Crypt/AuthEnc/ChaCha20Poly1305.pm index a8c17d6..0adf8a6 100644 --- a/lib/Crypt/AuthEnc/ChaCha20Poly1305.pm +++ b/lib/Crypt/AuthEnc/ChaCha20Poly1305.pm @@ -2,9 +2,9 @@ use strict; use warnings; -our $VERSION = '0.066'; +our $VERSION = '0.067'; -require Exporter; our @ISA = qw(Exporter); ### use Exporter 'import'; +require Exporter; our @ISA = qw(Exporter); ### use Exporter 5.57 'import'; our %EXPORT_TAGS = ( all => [qw( chacha20poly1305_encrypt_authenticate chacha20poly1305_decrypt_verify )] ); our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } ); our @EXPORT = qw(); diff --git a/lib/Crypt/AuthEnc/EAX.pm b/lib/Crypt/AuthEnc/EAX.pm index 8ef2f93..ae9e259 100644 --- a/lib/Crypt/AuthEnc/EAX.pm +++ b/lib/Crypt/AuthEnc/EAX.pm @@ -2,9 +2,9 @@ use strict; use warnings; -our $VERSION = '0.066'; +our $VERSION = '0.067'; -require Exporter; our @ISA = qw(Exporter); ### use Exporter 'import'; +require Exporter; our @ISA = qw(Exporter); ### use Exporter 5.57 'import'; our %EXPORT_TAGS = ( all => [qw( eax_encrypt_authenticate eax_decrypt_verify )] ); our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } ); our @EXPORT = qw(); diff --git a/lib/Crypt/AuthEnc/GCM.pm b/lib/Crypt/AuthEnc/GCM.pm index 9c84af0..1b0a342 100644 --- a/lib/Crypt/AuthEnc/GCM.pm +++ b/lib/Crypt/AuthEnc/GCM.pm @@ -2,9 +2,9 @@ use strict; use warnings; -our $VERSION = '0.066'; +our $VERSION = '0.067'; -require Exporter; our @ISA = qw(Exporter); ### use Exporter 'import'; +require Exporter; our @ISA = qw(Exporter); ### use Exporter 5.57 'import'; our %EXPORT_TAGS = ( all => [qw( gcm_encrypt_authenticate gcm_decrypt_verify )] ); our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } ); our @EXPORT = qw(); diff --git a/lib/Crypt/AuthEnc/OCB.pm b/lib/Crypt/AuthEnc/OCB.pm index a4efd7e..b6e62ab 100644 --- a/lib/Crypt/AuthEnc/OCB.pm +++ b/lib/Crypt/AuthEnc/OCB.pm @@ -2,9 +2,9 @@ use strict; use warnings; -our $VERSION = '0.066'; +our $VERSION = '0.067'; -require Exporter; our @ISA = qw(Exporter); ### use Exporter 'import'; +require Exporter; our @ISA = qw(Exporter); ### use Exporter 5.57 'import'; our %EXPORT_TAGS = ( all => [qw( ocb_encrypt_authenticate ocb_decrypt_verify )] ); our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } ); our @EXPORT = qw(); diff --git a/lib/Crypt/AuthEnc.pm b/lib/Crypt/AuthEnc.pm index 538ed54..0a4ad11 100644 --- a/lib/Crypt/AuthEnc.pm +++ b/lib/Crypt/AuthEnc.pm @@ -2,7 +2,7 @@ use strict; use warnings; -our $VERSION = '0.066'; +our $VERSION = '0.067'; ### not used diff --git a/lib/Crypt/Checksum/Adler32.pm b/lib/Crypt/Checksum/Adler32.pm index 85e86e5..d3fca09 100644 --- a/lib/Crypt/Checksum/Adler32.pm +++ b/lib/Crypt/Checksum/Adler32.pm @@ -2,7 +2,7 @@ use strict; use warnings; -our $VERSION = '0.066'; +our $VERSION = '0.067'; use base qw(Crypt::Checksum Exporter); our %EXPORT_TAGS = ( all => [qw( adler32_data adler32_data_hex adler32_data_int adler32_file adler32_file_hex adler32_file_int )] ); diff --git a/lib/Crypt/Checksum/CRC32.pm b/lib/Crypt/Checksum/CRC32.pm index ed93524..5fcf2c0 100644 --- a/lib/Crypt/Checksum/CRC32.pm +++ b/lib/Crypt/Checksum/CRC32.pm @@ -2,7 +2,7 @@ use strict; use warnings; -our $VERSION = '0.066'; +our $VERSION = '0.067'; use base qw(Crypt::Checksum Exporter); our %EXPORT_TAGS = ( all => [qw( crc32_data crc32_data_hex crc32_data_int crc32_file crc32_file_hex crc32_file_int )] ); diff --git a/lib/Crypt/Checksum.pm b/lib/Crypt/Checksum.pm index 923100e..b33bc1f 100644 --- a/lib/Crypt/Checksum.pm +++ b/lib/Crypt/Checksum.pm @@ -2,9 +2,9 @@ use strict; use warnings; -our $VERSION = '0.066'; +our $VERSION = '0.067'; -require Exporter; our @ISA = qw(Exporter); ### use Exporter 'import'; +require Exporter; our @ISA = qw(Exporter); ### use Exporter 5.57 'import'; our %EXPORT_TAGS = ( all => [qw/ adler32_data adler32_data_hex adler32_data_int adler32_file adler32_file_hex adler32_file_int crc32_data crc32_data_hex crc32_data_int crc32_file crc32_file_hex crc32_file_int /] ); our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } ); diff --git a/lib/Crypt/Cipher/AES.pm b/lib/Crypt/Cipher/AES.pm index 9888578..96eb3a9 100644 --- a/lib/Crypt/Cipher/AES.pm +++ b/lib/Crypt/Cipher/AES.pm @@ -4,7 +4,7 @@ use strict; use warnings; -our $VERSION = '0.066'; +our $VERSION = '0.067'; use base qw(Crypt::Cipher); diff --git a/lib/Crypt/Cipher/Anubis.pm b/lib/Crypt/Cipher/Anubis.pm index 406d7e9..2de7b1c 100644 --- a/lib/Crypt/Cipher/Anubis.pm +++ b/lib/Crypt/Cipher/Anubis.pm @@ -4,7 +4,7 @@ use strict; use warnings; -our $VERSION = '0.066'; +our $VERSION = '0.067'; use base qw(Crypt::Cipher); diff --git a/lib/Crypt/Cipher/Blowfish.pm b/lib/Crypt/Cipher/Blowfish.pm index 5db6217..9640251 100644 --- a/lib/Crypt/Cipher/Blowfish.pm +++ b/lib/Crypt/Cipher/Blowfish.pm @@ -4,7 +4,7 @@ use strict; use warnings; -our $VERSION = '0.066'; +our $VERSION = '0.067'; use base qw(Crypt::Cipher); diff --git a/lib/Crypt/Cipher/CAST5.pm b/lib/Crypt/Cipher/CAST5.pm index f09ec0c..e04de7a 100644 --- a/lib/Crypt/Cipher/CAST5.pm +++ b/lib/Crypt/Cipher/CAST5.pm @@ -4,7 +4,7 @@ use strict; use warnings; -our $VERSION = '0.066'; +our $VERSION = '0.067'; use base qw(Crypt::Cipher); diff --git a/lib/Crypt/Cipher/Camellia.pm b/lib/Crypt/Cipher/Camellia.pm index 4cd085e..a897c88 100644 --- a/lib/Crypt/Cipher/Camellia.pm +++ b/lib/Crypt/Cipher/Camellia.pm @@ -4,7 +4,7 @@ use strict; use warnings; -our $VERSION = '0.066'; +our $VERSION = '0.067'; use base qw(Crypt::Cipher); diff --git a/lib/Crypt/Cipher/DES.pm b/lib/Crypt/Cipher/DES.pm index 90a65dd..46d98cf 100644 --- a/lib/Crypt/Cipher/DES.pm +++ b/lib/Crypt/Cipher/DES.pm @@ -4,7 +4,7 @@ use strict; use warnings; -our $VERSION = '0.066'; +our $VERSION = '0.067'; use base qw(Crypt::Cipher); diff --git a/lib/Crypt/Cipher/DES_EDE.pm b/lib/Crypt/Cipher/DES_EDE.pm index 691cae9..d1b1445 100644 --- a/lib/Crypt/Cipher/DES_EDE.pm +++ b/lib/Crypt/Cipher/DES_EDE.pm @@ -4,7 +4,7 @@ use strict; use warnings; -our $VERSION = '0.066'; +our $VERSION = '0.067'; use base qw(Crypt::Cipher); diff --git a/lib/Crypt/Cipher/IDEA.pm b/lib/Crypt/Cipher/IDEA.pm index 36ae5e4..1248460 100644 --- a/lib/Crypt/Cipher/IDEA.pm +++ b/lib/Crypt/Cipher/IDEA.pm @@ -4,7 +4,7 @@ use strict; use warnings; -our $VERSION = '0.066'; +our $VERSION = '0.067'; use base qw(Crypt::Cipher); diff --git a/lib/Crypt/Cipher/KASUMI.pm b/lib/Crypt/Cipher/KASUMI.pm index f8e9a27..365cd22 100644 --- a/lib/Crypt/Cipher/KASUMI.pm +++ b/lib/Crypt/Cipher/KASUMI.pm @@ -4,7 +4,7 @@ use strict; use warnings; -our $VERSION = '0.066'; +our $VERSION = '0.067'; use base qw(Crypt::Cipher); diff --git a/lib/Crypt/Cipher/Khazad.pm b/lib/Crypt/Cipher/Khazad.pm index 281ec54..1982f24 100644 --- a/lib/Crypt/Cipher/Khazad.pm +++ b/lib/Crypt/Cipher/Khazad.pm @@ -4,7 +4,7 @@ use strict; use warnings; -our $VERSION = '0.066'; +our $VERSION = '0.067'; use base qw(Crypt::Cipher); diff --git a/lib/Crypt/Cipher/MULTI2.pm b/lib/Crypt/Cipher/MULTI2.pm index cf7b29e..b157167 100644 --- a/lib/Crypt/Cipher/MULTI2.pm +++ b/lib/Crypt/Cipher/MULTI2.pm @@ -4,7 +4,7 @@ use strict; use warnings; -our $VERSION = '0.066'; +our $VERSION = '0.067'; use base qw(Crypt::Cipher); diff --git a/lib/Crypt/Cipher/Noekeon.pm b/lib/Crypt/Cipher/Noekeon.pm index b7c9072..d5764fc 100644 --- a/lib/Crypt/Cipher/Noekeon.pm +++ b/lib/Crypt/Cipher/Noekeon.pm @@ -4,7 +4,7 @@ use strict; use warnings; -our $VERSION = '0.066'; +our $VERSION = '0.067'; use base qw(Crypt::Cipher); diff --git a/lib/Crypt/Cipher/RC2.pm b/lib/Crypt/Cipher/RC2.pm index 60ca687..cdd019d 100644 --- a/lib/Crypt/Cipher/RC2.pm +++ b/lib/Crypt/Cipher/RC2.pm @@ -4,7 +4,7 @@ use strict; use warnings; -our $VERSION = '0.066'; +our $VERSION = '0.067'; use base qw(Crypt::Cipher); diff --git a/lib/Crypt/Cipher/RC5.pm b/lib/Crypt/Cipher/RC5.pm index 4c01d85..fe63eb9 100644 --- a/lib/Crypt/Cipher/RC5.pm +++ b/lib/Crypt/Cipher/RC5.pm @@ -4,7 +4,7 @@ use strict; use warnings; -our $VERSION = '0.066'; +our $VERSION = '0.067'; use base qw(Crypt::Cipher); diff --git a/lib/Crypt/Cipher/RC6.pm b/lib/Crypt/Cipher/RC6.pm index e673cd9..f86d514 100644 --- a/lib/Crypt/Cipher/RC6.pm +++ b/lib/Crypt/Cipher/RC6.pm @@ -4,7 +4,7 @@ use strict; use warnings; -our $VERSION = '0.066'; +our $VERSION = '0.067'; use base qw(Crypt::Cipher); diff --git a/lib/Crypt/Cipher/SAFERP.pm b/lib/Crypt/Cipher/SAFERP.pm index c932ecc..c108a70 100644 --- a/lib/Crypt/Cipher/SAFERP.pm +++ b/lib/Crypt/Cipher/SAFERP.pm @@ -4,7 +4,7 @@ use strict; use warnings; -our $VERSION = '0.066'; +our $VERSION = '0.067'; use base qw(Crypt::Cipher); diff --git a/lib/Crypt/Cipher/SAFER_K128.pm b/lib/Crypt/Cipher/SAFER_K128.pm index 1420fd0..7b92336 100644 --- a/lib/Crypt/Cipher/SAFER_K128.pm +++ b/lib/Crypt/Cipher/SAFER_K128.pm @@ -4,7 +4,7 @@ use strict; use warnings; -our $VERSION = '0.066'; +our $VERSION = '0.067'; use base qw(Crypt::Cipher); diff --git a/lib/Crypt/Cipher/SAFER_K64.pm b/lib/Crypt/Cipher/SAFER_K64.pm index 17f4c7a..4fe210b 100644 --- a/lib/Crypt/Cipher/SAFER_K64.pm +++ b/lib/Crypt/Cipher/SAFER_K64.pm @@ -4,7 +4,7 @@ use strict; use warnings; -our $VERSION = '0.066'; +our $VERSION = '0.067'; use base qw(Crypt::Cipher); diff --git a/lib/Crypt/Cipher/SAFER_SK128.pm b/lib/Crypt/Cipher/SAFER_SK128.pm index 4a9b6f4..fcea82d 100644 --- a/lib/Crypt/Cipher/SAFER_SK128.pm +++ b/lib/Crypt/Cipher/SAFER_SK128.pm @@ -4,7 +4,7 @@ use strict; use warnings; -our $VERSION = '0.066'; +our $VERSION = '0.067'; use base qw(Crypt::Cipher); diff --git a/lib/Crypt/Cipher/SAFER_SK64.pm b/lib/Crypt/Cipher/SAFER_SK64.pm index 6dc37f4..db996b0 100644 --- a/lib/Crypt/Cipher/SAFER_SK64.pm +++ b/lib/Crypt/Cipher/SAFER_SK64.pm @@ -4,7 +4,7 @@ use strict; use warnings; -our $VERSION = '0.066'; +our $VERSION = '0.067'; use base qw(Crypt::Cipher); diff --git a/lib/Crypt/Cipher/SEED.pm b/lib/Crypt/Cipher/SEED.pm index 105f8ad..4671568 100644 --- a/lib/Crypt/Cipher/SEED.pm +++ b/lib/Crypt/Cipher/SEED.pm @@ -4,7 +4,7 @@ use strict; use warnings; -our $VERSION = '0.066'; +our $VERSION = '0.067'; use base qw(Crypt::Cipher); diff --git a/lib/Crypt/Cipher/Serpent.pm b/lib/Crypt/Cipher/Serpent.pm index 2351505..580ffeb 100644 --- a/lib/Crypt/Cipher/Serpent.pm +++ b/lib/Crypt/Cipher/Serpent.pm @@ -4,7 +4,7 @@ use strict; use warnings; -our $VERSION = '0.066'; +our $VERSION = '0.067'; use base qw(Crypt::Cipher); diff --git a/lib/Crypt/Cipher/Skipjack.pm b/lib/Crypt/Cipher/Skipjack.pm index 0ff4553..494f8dd 100644 --- a/lib/Crypt/Cipher/Skipjack.pm +++ b/lib/Crypt/Cipher/Skipjack.pm @@ -4,7 +4,7 @@ use strict; use warnings; -our $VERSION = '0.066'; +our $VERSION = '0.067'; use base qw(Crypt::Cipher); diff --git a/lib/Crypt/Cipher/Twofish.pm b/lib/Crypt/Cipher/Twofish.pm index bc8cb3a..dc0cc81 100644 --- a/lib/Crypt/Cipher/Twofish.pm +++ b/lib/Crypt/Cipher/Twofish.pm @@ -4,7 +4,7 @@ use strict; use warnings; -our $VERSION = '0.066'; +our $VERSION = '0.067'; use base qw(Crypt::Cipher); diff --git a/lib/Crypt/Cipher/XTEA.pm b/lib/Crypt/Cipher/XTEA.pm index c589667..ffeb204 100644 --- a/lib/Crypt/Cipher/XTEA.pm +++ b/lib/Crypt/Cipher/XTEA.pm @@ -4,7 +4,7 @@ use strict; use warnings; -our $VERSION = '0.066'; +our $VERSION = '0.067'; use base qw(Crypt::Cipher); diff --git a/lib/Crypt/Cipher.pm b/lib/Crypt/Cipher.pm index 0712d57..cc99b0c 100644 --- a/lib/Crypt/Cipher.pm +++ b/lib/Crypt/Cipher.pm @@ -2,7 +2,7 @@ use strict; use warnings; -our $VERSION = '0.066'; +our $VERSION = '0.067'; use Carp; $Carp::Internal{(__PACKAGE__)}++; diff --git a/lib/Crypt/Digest/BLAKE2b_160.pm b/lib/Crypt/Digest/BLAKE2b_160.pm index d0aa244..b0259d4 100644 --- a/lib/Crypt/Digest/BLAKE2b_160.pm +++ b/lib/Crypt/Digest/BLAKE2b_160.pm @@ -4,7 +4,7 @@ use strict; use warnings; -our $VERSION = '0.066'; +our $VERSION = '0.067'; use base qw(Crypt::Digest Exporter); 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 )] ); diff --git a/lib/Crypt/Digest/BLAKE2b_256.pm b/lib/Crypt/Digest/BLAKE2b_256.pm index a1b22d9..07b6e6e 100644 --- a/lib/Crypt/Digest/BLAKE2b_256.pm +++ b/lib/Crypt/Digest/BLAKE2b_256.pm @@ -4,7 +4,7 @@ use strict; use warnings; -our $VERSION = '0.066'; +our $VERSION = '0.067'; use base qw(Crypt::Digest Exporter); 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 )] ); diff --git a/lib/Crypt/Digest/BLAKE2b_384.pm b/lib/Crypt/Digest/BLAKE2b_384.pm index 5267e10..bf78b08 100644 --- a/lib/Crypt/Digest/BLAKE2b_384.pm +++ b/lib/Crypt/Digest/BLAKE2b_384.pm @@ -4,7 +4,7 @@ use strict; use warnings; -our $VERSION = '0.066'; +our $VERSION = '0.067'; use base qw(Crypt::Digest Exporter); 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 )] ); diff --git a/lib/Crypt/Digest/BLAKE2b_512.pm b/lib/Crypt/Digest/BLAKE2b_512.pm index dc754c7..2621e7a 100644 --- a/lib/Crypt/Digest/BLAKE2b_512.pm +++ b/lib/Crypt/Digest/BLAKE2b_512.pm @@ -4,7 +4,7 @@ use strict; use warnings; -our $VERSION = '0.066'; +our $VERSION = '0.067'; use base qw(Crypt::Digest Exporter); 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 )] ); diff --git a/lib/Crypt/Digest/BLAKE2s_128.pm b/lib/Crypt/Digest/BLAKE2s_128.pm index 91fa388..6316c9d 100644 --- a/lib/Crypt/Digest/BLAKE2s_128.pm +++ b/lib/Crypt/Digest/BLAKE2s_128.pm @@ -4,7 +4,7 @@ use strict; use warnings; -our $VERSION = '0.066'; +our $VERSION = '0.067'; use base qw(Crypt::Digest Exporter); 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 )] ); diff --git a/lib/Crypt/Digest/BLAKE2s_160.pm b/lib/Crypt/Digest/BLAKE2s_160.pm index 4bc57b3..4423e25 100644 --- a/lib/Crypt/Digest/BLAKE2s_160.pm +++ b/lib/Crypt/Digest/BLAKE2s_160.pm @@ -4,7 +4,7 @@ use strict; use warnings; -our $VERSION = '0.066'; +our $VERSION = '0.067'; use base qw(Crypt::Digest Exporter); 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 )] ); diff --git a/lib/Crypt/Digest/BLAKE2s_224.pm b/lib/Crypt/Digest/BLAKE2s_224.pm index 6a61af9..7437567 100644 --- a/lib/Crypt/Digest/BLAKE2s_224.pm +++ b/lib/Crypt/Digest/BLAKE2s_224.pm @@ -4,7 +4,7 @@ use strict; use warnings; -our $VERSION = '0.066'; +our $VERSION = '0.067'; use base qw(Crypt::Digest Exporter); 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 )] ); diff --git a/lib/Crypt/Digest/BLAKE2s_256.pm b/lib/Crypt/Digest/BLAKE2s_256.pm index 8ae837b..81212ba 100644 --- a/lib/Crypt/Digest/BLAKE2s_256.pm +++ b/lib/Crypt/Digest/BLAKE2s_256.pm @@ -4,7 +4,7 @@ use strict; use warnings; -our $VERSION = '0.066'; +our $VERSION = '0.067'; use base qw(Crypt::Digest Exporter); 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 )] ); diff --git a/lib/Crypt/Digest/CHAES.pm b/lib/Crypt/Digest/CHAES.pm index d465821..3cbbc8e 100644 --- a/lib/Crypt/Digest/CHAES.pm +++ b/lib/Crypt/Digest/CHAES.pm @@ -4,7 +4,7 @@ use strict; use warnings; -our $VERSION = '0.066'; +our $VERSION = '0.067'; use base qw(Crypt::Digest Exporter); our %EXPORT_TAGS = ( all => [qw( chaes chaes_hex chaes_b64 chaes_b64u chaes_file chaes_file_hex chaes_file_b64 chaes_file_b64u )] ); diff --git a/lib/Crypt/Digest/Keccak224.pm b/lib/Crypt/Digest/Keccak224.pm index ab11ddb..e3bbd7f 100644 --- a/lib/Crypt/Digest/Keccak224.pm +++ b/lib/Crypt/Digest/Keccak224.pm @@ -4,7 +4,7 @@ use strict; use warnings; -our $VERSION = '0.066'; +our $VERSION = '0.067'; use base qw(Crypt::Digest Exporter); our %EXPORT_TAGS = ( all => [qw( keccak224 keccak224_hex keccak224_b64 keccak224_b64u keccak224_file keccak224_file_hex keccak224_file_b64 keccak224_file_b64u )] ); diff --git a/lib/Crypt/Digest/Keccak256.pm b/lib/Crypt/Digest/Keccak256.pm index 1775c65..020d6d8 100644 --- a/lib/Crypt/Digest/Keccak256.pm +++ b/lib/Crypt/Digest/Keccak256.pm @@ -4,7 +4,7 @@ use strict; use warnings; -our $VERSION = '0.066'; +our $VERSION = '0.067'; use base qw(Crypt::Digest Exporter); our %EXPORT_TAGS = ( all => [qw( keccak256 keccak256_hex keccak256_b64 keccak256_b64u keccak256_file keccak256_file_hex keccak256_file_b64 keccak256_file_b64u )] ); diff --git a/lib/Crypt/Digest/Keccak384.pm b/lib/Crypt/Digest/Keccak384.pm index db2a590..53408e2 100644 --- a/lib/Crypt/Digest/Keccak384.pm +++ b/lib/Crypt/Digest/Keccak384.pm @@ -4,7 +4,7 @@ use strict; use warnings; -our $VERSION = '0.066'; +our $VERSION = '0.067'; use base qw(Crypt::Digest Exporter); our %EXPORT_TAGS = ( all => [qw( keccak384 keccak384_hex keccak384_b64 keccak384_b64u keccak384_file keccak384_file_hex keccak384_file_b64 keccak384_file_b64u )] ); diff --git a/lib/Crypt/Digest/Keccak512.pm b/lib/Crypt/Digest/Keccak512.pm index 2493df4..c7c711b 100644 --- a/lib/Crypt/Digest/Keccak512.pm +++ b/lib/Crypt/Digest/Keccak512.pm @@ -4,7 +4,7 @@ use strict; use warnings; -our $VERSION = '0.066'; +our $VERSION = '0.067'; use base qw(Crypt::Digest Exporter); our %EXPORT_TAGS = ( all => [qw( keccak512 keccak512_hex keccak512_b64 keccak512_b64u keccak512_file keccak512_file_hex keccak512_file_b64 keccak512_file_b64u )] ); diff --git a/lib/Crypt/Digest/MD2.pm b/lib/Crypt/Digest/MD2.pm index ec6e2f6..911b071 100644 --- a/lib/Crypt/Digest/MD2.pm +++ b/lib/Crypt/Digest/MD2.pm @@ -4,7 +4,7 @@ use strict; use warnings; -our $VERSION = '0.066'; +our $VERSION = '0.067'; use base qw(Crypt::Digest Exporter); our %EXPORT_TAGS = ( all => [qw( md2 md2_hex md2_b64 md2_b64u md2_file md2_file_hex md2_file_b64 md2_file_b64u )] ); diff --git a/lib/Crypt/Digest/MD4.pm b/lib/Crypt/Digest/MD4.pm index c87cd9f..0087727 100644 --- a/lib/Crypt/Digest/MD4.pm +++ b/lib/Crypt/Digest/MD4.pm @@ -4,7 +4,7 @@ use strict; use warnings; -our $VERSION = '0.066'; +our $VERSION = '0.067'; use base qw(Crypt::Digest Exporter); our %EXPORT_TAGS = ( all => [qw( md4 md4_hex md4_b64 md4_b64u md4_file md4_file_hex md4_file_b64 md4_file_b64u )] ); diff --git a/lib/Crypt/Digest/MD5.pm b/lib/Crypt/Digest/MD5.pm index d5e309b..e6749f7 100644 --- a/lib/Crypt/Digest/MD5.pm +++ b/lib/Crypt/Digest/MD5.pm @@ -4,7 +4,7 @@ use strict; use warnings; -our $VERSION = '0.066'; +our $VERSION = '0.067'; use base qw(Crypt::Digest Exporter); our %EXPORT_TAGS = ( all => [qw( md5 md5_hex md5_b64 md5_b64u md5_file md5_file_hex md5_file_b64 md5_file_b64u )] ); diff --git a/lib/Crypt/Digest/RIPEMD128.pm b/lib/Crypt/Digest/RIPEMD128.pm index 63476a0..c11b16f 100644 --- a/lib/Crypt/Digest/RIPEMD128.pm +++ b/lib/Crypt/Digest/RIPEMD128.pm @@ -4,7 +4,7 @@ use strict; use warnings; -our $VERSION = '0.066'; +our $VERSION = '0.067'; use base qw(Crypt::Digest Exporter); our %EXPORT_TAGS = ( all => [qw( ripemd128 ripemd128_hex ripemd128_b64 ripemd128_b64u ripemd128_file ripemd128_file_hex ripemd128_file_b64 ripemd128_file_b64u )] ); diff --git a/lib/Crypt/Digest/RIPEMD160.pm b/lib/Crypt/Digest/RIPEMD160.pm index c5260d4..55fac19 100644 --- a/lib/Crypt/Digest/RIPEMD160.pm +++ b/lib/Crypt/Digest/RIPEMD160.pm @@ -4,7 +4,7 @@ use strict; use warnings; -our $VERSION = '0.066'; +our $VERSION = '0.067'; use base qw(Crypt::Digest Exporter); our %EXPORT_TAGS = ( all => [qw( ripemd160 ripemd160_hex ripemd160_b64 ripemd160_b64u ripemd160_file ripemd160_file_hex ripemd160_file_b64 ripemd160_file_b64u )] ); diff --git a/lib/Crypt/Digest/RIPEMD256.pm b/lib/Crypt/Digest/RIPEMD256.pm index cfd994e..622e75d 100644 --- a/lib/Crypt/Digest/RIPEMD256.pm +++ b/lib/Crypt/Digest/RIPEMD256.pm @@ -4,7 +4,7 @@ use strict; use warnings; -our $VERSION = '0.066'; +our $VERSION = '0.067'; use base qw(Crypt::Digest Exporter); our %EXPORT_TAGS = ( all => [qw( ripemd256 ripemd256_hex ripemd256_b64 ripemd256_b64u ripemd256_file ripemd256_file_hex ripemd256_file_b64 ripemd256_file_b64u )] ); diff --git a/lib/Crypt/Digest/RIPEMD320.pm b/lib/Crypt/Digest/RIPEMD320.pm index 36447af..ee8967d 100644 --- a/lib/Crypt/Digest/RIPEMD320.pm +++ b/lib/Crypt/Digest/RIPEMD320.pm @@ -4,7 +4,7 @@ use strict; use warnings; -our $VERSION = '0.066'; +our $VERSION = '0.067'; use base qw(Crypt::Digest Exporter); our %EXPORT_TAGS = ( all => [qw( ripemd320 ripemd320_hex ripemd320_b64 ripemd320_b64u ripemd320_file ripemd320_file_hex ripemd320_file_b64 ripemd320_file_b64u )] ); diff --git a/lib/Crypt/Digest/SHA1.pm b/lib/Crypt/Digest/SHA1.pm index fb1a595..b52a348 100644 --- a/lib/Crypt/Digest/SHA1.pm +++ b/lib/Crypt/Digest/SHA1.pm @@ -4,7 +4,7 @@ use strict; use warnings; -our $VERSION = '0.066'; +our $VERSION = '0.067'; use base qw(Crypt::Digest Exporter); our %EXPORT_TAGS = ( all => [qw( sha1 sha1_hex sha1_b64 sha1_b64u sha1_file sha1_file_hex sha1_file_b64 sha1_file_b64u )] ); diff --git a/lib/Crypt/Digest/SHA224.pm b/lib/Crypt/Digest/SHA224.pm index 048bc70..5d3c3cf 100644 --- a/lib/Crypt/Digest/SHA224.pm +++ b/lib/Crypt/Digest/SHA224.pm @@ -4,7 +4,7 @@ use strict; use warnings; -our $VERSION = '0.066'; +our $VERSION = '0.067'; use base qw(Crypt::Digest Exporter); our %EXPORT_TAGS = ( all => [qw( sha224 sha224_hex sha224_b64 sha224_b64u sha224_file sha224_file_hex sha224_file_b64 sha224_file_b64u )] ); diff --git a/lib/Crypt/Digest/SHA256.pm b/lib/Crypt/Digest/SHA256.pm index e770634..d9525f6 100644 --- a/lib/Crypt/Digest/SHA256.pm +++ b/lib/Crypt/Digest/SHA256.pm @@ -4,7 +4,7 @@ use strict; use warnings; -our $VERSION = '0.066'; +our $VERSION = '0.067'; use base qw(Crypt::Digest Exporter); our %EXPORT_TAGS = ( all => [qw( sha256 sha256_hex sha256_b64 sha256_b64u sha256_file sha256_file_hex sha256_file_b64 sha256_file_b64u )] ); diff --git a/lib/Crypt/Digest/SHA384.pm b/lib/Crypt/Digest/SHA384.pm index 9f4dfe4..a25afef 100644 --- a/lib/Crypt/Digest/SHA384.pm +++ b/lib/Crypt/Digest/SHA384.pm @@ -4,7 +4,7 @@ use strict; use warnings; -our $VERSION = '0.066'; +our $VERSION = '0.067'; use base qw(Crypt::Digest Exporter); our %EXPORT_TAGS = ( all => [qw( sha384 sha384_hex sha384_b64 sha384_b64u sha384_file sha384_file_hex sha384_file_b64 sha384_file_b64u )] ); diff --git a/lib/Crypt/Digest/SHA3_224.pm b/lib/Crypt/Digest/SHA3_224.pm index 66ca740..b6b2d73 100644 --- a/lib/Crypt/Digest/SHA3_224.pm +++ b/lib/Crypt/Digest/SHA3_224.pm @@ -4,7 +4,7 @@ use strict; use warnings; -our $VERSION = '0.066'; +our $VERSION = '0.067'; use base qw(Crypt::Digest Exporter); 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 )] ); diff --git a/lib/Crypt/Digest/SHA3_256.pm b/lib/Crypt/Digest/SHA3_256.pm index 1b7efe2..6b96e53 100644 --- a/lib/Crypt/Digest/SHA3_256.pm +++ b/lib/Crypt/Digest/SHA3_256.pm @@ -4,7 +4,7 @@ use strict; use warnings; -our $VERSION = '0.066'; +our $VERSION = '0.067'; use base qw(Crypt::Digest Exporter); 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 )] ); diff --git a/lib/Crypt/Digest/SHA3_384.pm b/lib/Crypt/Digest/SHA3_384.pm index 6a9ed9b..117c17d 100644 --- a/lib/Crypt/Digest/SHA3_384.pm +++ b/lib/Crypt/Digest/SHA3_384.pm @@ -4,7 +4,7 @@ use strict; use warnings; -our $VERSION = '0.066'; +our $VERSION = '0.067'; use base qw(Crypt::Digest Exporter); 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 )] ); diff --git a/lib/Crypt/Digest/SHA3_512.pm b/lib/Crypt/Digest/SHA3_512.pm index 1ef57c2..9a678ec 100644 --- a/lib/Crypt/Digest/SHA3_512.pm +++ b/lib/Crypt/Digest/SHA3_512.pm @@ -4,7 +4,7 @@ use strict; use warnings; -our $VERSION = '0.066'; +our $VERSION = '0.067'; use base qw(Crypt::Digest Exporter); 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 )] ); diff --git a/lib/Crypt/Digest/SHA512.pm b/lib/Crypt/Digest/SHA512.pm index bcc7858..cb301a1 100644 --- a/lib/Crypt/Digest/SHA512.pm +++ b/lib/Crypt/Digest/SHA512.pm @@ -4,7 +4,7 @@ use strict; use warnings; -our $VERSION = '0.066'; +our $VERSION = '0.067'; use base qw(Crypt::Digest Exporter); our %EXPORT_TAGS = ( all => [qw( sha512 sha512_hex sha512_b64 sha512_b64u sha512_file sha512_file_hex sha512_file_b64 sha512_file_b64u )] ); diff --git a/lib/Crypt/Digest/SHA512_224.pm b/lib/Crypt/Digest/SHA512_224.pm index 91318a3..ac63864 100644 --- a/lib/Crypt/Digest/SHA512_224.pm +++ b/lib/Crypt/Digest/SHA512_224.pm @@ -4,7 +4,7 @@ use strict; use warnings; -our $VERSION = '0.066'; +our $VERSION = '0.067'; use base qw(Crypt::Digest Exporter); 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 )] ); diff --git a/lib/Crypt/Digest/SHA512_256.pm b/lib/Crypt/Digest/SHA512_256.pm index 1301aa0..4a456da 100644 --- a/lib/Crypt/Digest/SHA512_256.pm +++ b/lib/Crypt/Digest/SHA512_256.pm @@ -4,7 +4,7 @@ use strict; use warnings; -our $VERSION = '0.066'; +our $VERSION = '0.067'; use base qw(Crypt::Digest Exporter); 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 )] ); diff --git a/lib/Crypt/Digest/SHAKE.pm b/lib/Crypt/Digest/SHAKE.pm index 47a96db..a613335 100644 --- a/lib/Crypt/Digest/SHAKE.pm +++ b/lib/Crypt/Digest/SHAKE.pm @@ -2,7 +2,7 @@ use strict; use warnings; -our $VERSION = '0.066'; +our $VERSION = '0.067'; use Carp; $Carp::Internal{(__PACKAGE__)}++; diff --git a/lib/Crypt/Digest/Tiger192.pm b/lib/Crypt/Digest/Tiger192.pm index b8cea08..fe2b1b7 100644 --- a/lib/Crypt/Digest/Tiger192.pm +++ b/lib/Crypt/Digest/Tiger192.pm @@ -4,7 +4,7 @@ use strict; use warnings; -our $VERSION = '0.066'; +our $VERSION = '0.067'; use base qw(Crypt::Digest Exporter); our %EXPORT_TAGS = ( all => [qw( tiger192 tiger192_hex tiger192_b64 tiger192_b64u tiger192_file tiger192_file_hex tiger192_file_b64 tiger192_file_b64u )] ); diff --git a/lib/Crypt/Digest/Whirlpool.pm b/lib/Crypt/Digest/Whirlpool.pm index a412488..ac35b3d 100644 --- a/lib/Crypt/Digest/Whirlpool.pm +++ b/lib/Crypt/Digest/Whirlpool.pm @@ -4,7 +4,7 @@ use strict; use warnings; -our $VERSION = '0.066'; +our $VERSION = '0.067'; use base qw(Crypt::Digest Exporter); our %EXPORT_TAGS = ( all => [qw( whirlpool whirlpool_hex whirlpool_b64 whirlpool_b64u whirlpool_file whirlpool_file_hex whirlpool_file_b64 whirlpool_file_b64u )] ); diff --git a/lib/Crypt/Digest.pm b/lib/Crypt/Digest.pm index 2acc050..4713373 100644 --- a/lib/Crypt/Digest.pm +++ b/lib/Crypt/Digest.pm @@ -2,9 +2,9 @@ use strict; use warnings; -our $VERSION = '0.066'; - -require Exporter; our @ISA = qw(Exporter); ### use Exporter 'import'; +our $VERSION = '0.067'; + +require Exporter; our @ISA = qw(Exporter); ### use Exporter 5.57 'import'; 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 )] ); our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } ); our @EXPORT = qw(); diff --git a/lib/Crypt/KeyDerivation.pm b/lib/Crypt/KeyDerivation.pm index 0dd03cd..001dcbe 100644 --- a/lib/Crypt/KeyDerivation.pm +++ b/lib/Crypt/KeyDerivation.pm @@ -2,9 +2,9 @@ use strict; use warnings; -our $VERSION = '0.066'; +our $VERSION = '0.067'; -require Exporter; our @ISA = qw(Exporter); ### use Exporter 'import'; +require Exporter; our @ISA = qw(Exporter); ### use Exporter 5.57 'import'; our %EXPORT_TAGS = ( all => [qw(pbkdf1 pbkdf2 hkdf hkdf_expand hkdf_extract)] ); our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } ); our @EXPORT = qw(); diff --git a/lib/Crypt/Mac/BLAKE2b.pm b/lib/Crypt/Mac/BLAKE2b.pm index 5c24dbc..81c1109 100644 --- a/lib/Crypt/Mac/BLAKE2b.pm +++ b/lib/Crypt/Mac/BLAKE2b.pm @@ -4,7 +4,7 @@ use strict; use warnings; -our $VERSION = '0.066'; +our $VERSION = '0.067'; use base qw(Crypt::Mac Exporter); our %EXPORT_TAGS = ( all => [qw( blake2b blake2b_hex blake2b_b64 blake2b_b64u )] ); diff --git a/lib/Crypt/Mac/BLAKE2s.pm b/lib/Crypt/Mac/BLAKE2s.pm index 4284424..1cb5dd2 100644 --- a/lib/Crypt/Mac/BLAKE2s.pm +++ b/lib/Crypt/Mac/BLAKE2s.pm @@ -4,7 +4,7 @@ use strict; use warnings; -our $VERSION = '0.066'; +our $VERSION = '0.067'; use base qw(Crypt::Mac Exporter); our %EXPORT_TAGS = ( all => [qw( blake2s blake2s_hex blake2s_b64 blake2s_b64u )] ); diff --git a/lib/Crypt/Mac/F9.pm b/lib/Crypt/Mac/F9.pm index 4bd75d5..f32d1ea 100644 --- a/lib/Crypt/Mac/F9.pm +++ b/lib/Crypt/Mac/F9.pm @@ -4,7 +4,7 @@ use strict; use warnings; -our $VERSION = '0.066'; +our $VERSION = '0.067'; use base qw(Crypt::Mac Exporter); our %EXPORT_TAGS = ( all => [qw( f9 f9_hex f9_b64 f9_b64u )] ); diff --git a/lib/Crypt/Mac/HMAC.pm b/lib/Crypt/Mac/HMAC.pm index 7acc1bd..db3b397 100644 --- a/lib/Crypt/Mac/HMAC.pm +++ b/lib/Crypt/Mac/HMAC.pm @@ -4,7 +4,7 @@ use strict; use warnings; -our $VERSION = '0.066'; +our $VERSION = '0.067'; use base qw(Crypt::Mac Exporter); our %EXPORT_TAGS = ( all => [qw( hmac hmac_hex hmac_b64 hmac_b64u )] ); diff --git a/lib/Crypt/Mac/OMAC.pm b/lib/Crypt/Mac/OMAC.pm index 5cd47b7..bbc040e 100644 --- a/lib/Crypt/Mac/OMAC.pm +++ b/lib/Crypt/Mac/OMAC.pm @@ -4,7 +4,7 @@ use strict; use warnings; -our $VERSION = '0.066'; +our $VERSION = '0.067'; use base qw(Crypt::Mac Exporter); our %EXPORT_TAGS = ( all => [qw( omac omac_hex omac_b64 omac_b64u )] ); diff --git a/lib/Crypt/Mac/PMAC.pm b/lib/Crypt/Mac/PMAC.pm index b46500a..88e27f9 100644 --- a/lib/Crypt/Mac/PMAC.pm +++ b/lib/Crypt/Mac/PMAC.pm @@ -4,7 +4,7 @@ use strict; use warnings; -our $VERSION = '0.066'; +our $VERSION = '0.067'; use base qw(Crypt::Mac Exporter); our %EXPORT_TAGS = ( all => [qw( pmac pmac_hex pmac_b64 pmac_b64u )] ); diff --git a/lib/Crypt/Mac/Pelican.pm b/lib/Crypt/Mac/Pelican.pm index 5863fe6..34803d7 100644 --- a/lib/Crypt/Mac/Pelican.pm +++ b/lib/Crypt/Mac/Pelican.pm @@ -4,7 +4,7 @@ use strict; use warnings; -our $VERSION = '0.066'; +our $VERSION = '0.067'; use base qw(Crypt::Mac Exporter); our %EXPORT_TAGS = ( all => [qw( pelican pelican_hex pelican_b64 pelican_b64u )] ); diff --git a/lib/Crypt/Mac/Poly1305.pm b/lib/Crypt/Mac/Poly1305.pm index ac3965a..0f65391 100644 --- a/lib/Crypt/Mac/Poly1305.pm +++ b/lib/Crypt/Mac/Poly1305.pm @@ -4,7 +4,7 @@ use strict; use warnings; -our $VERSION = '0.066'; +our $VERSION = '0.067'; use base qw(Crypt::Mac Exporter); our %EXPORT_TAGS = ( all => [qw( poly1305 poly1305_hex poly1305_b64 poly1305_b64u )] ); diff --git a/lib/Crypt/Mac/XCBC.pm b/lib/Crypt/Mac/XCBC.pm index 844d852..5f77916 100644 --- a/lib/Crypt/Mac/XCBC.pm +++ b/lib/Crypt/Mac/XCBC.pm @@ -4,7 +4,7 @@ use strict; use warnings; -our $VERSION = '0.066'; +our $VERSION = '0.067'; use base qw(Crypt::Mac Exporter); our %EXPORT_TAGS = ( all => [qw( xcbc xcbc_hex xcbc_b64 xcbc_b64u )] ); diff --git a/lib/Crypt/Mac.pm b/lib/Crypt/Mac.pm index 4271a7d..2bd7911 100644 --- a/lib/Crypt/Mac.pm +++ b/lib/Crypt/Mac.pm @@ -2,7 +2,7 @@ use strict; use warnings; -our $VERSION = '0.066'; +our $VERSION = '0.067'; use Carp; $Carp::Internal{(__PACKAGE__)}++; diff --git a/lib/Crypt/Misc.pm b/lib/Crypt/Misc.pm index e7a273c..7c632fe 100644 --- a/lib/Crypt/Misc.pm +++ b/lib/Crypt/Misc.pm @@ -2,7 +2,7 @@ use strict; use warnings; -our $VERSION = '0.066'; +our $VERSION = '0.067'; require Exporter; our @ISA = qw(Exporter); ### use Exporter 5.57 'import'; use Carp 'croak'; diff --git a/lib/Crypt/Mode/CBC.pm b/lib/Crypt/Mode/CBC.pm index 7d73ced..94bc6ae 100644 --- a/lib/Crypt/Mode/CBC.pm +++ b/lib/Crypt/Mode/CBC.pm @@ -4,7 +4,7 @@ use strict; use warnings; -our $VERSION = '0.066'; +our $VERSION = '0.067'; use Crypt::Cipher; diff --git a/lib/Crypt/Mode/CFB.pm b/lib/Crypt/Mode/CFB.pm index b86a50e..e8326a6 100644 --- a/lib/Crypt/Mode/CFB.pm +++ b/lib/Crypt/Mode/CFB.pm @@ -4,7 +4,7 @@ use strict; use warnings; -our $VERSION = '0.066'; +our $VERSION = '0.067'; use Crypt::Cipher; diff --git a/lib/Crypt/Mode/CTR.pm b/lib/Crypt/Mode/CTR.pm index 529f9bf..6237cf2 100644 --- a/lib/Crypt/Mode/CTR.pm +++ b/lib/Crypt/Mode/CTR.pm @@ -4,7 +4,7 @@ use strict; use warnings; -our $VERSION = '0.066'; +our $VERSION = '0.067'; use Crypt::Cipher; diff --git a/lib/Crypt/Mode/ECB.pm b/lib/Crypt/Mode/ECB.pm index 2ace752..d731380 100644 --- a/lib/Crypt/Mode/ECB.pm +++ b/lib/Crypt/Mode/ECB.pm @@ -4,7 +4,7 @@ use strict; use warnings; -our $VERSION = '0.066'; +our $VERSION = '0.067'; use Crypt::Cipher; diff --git a/lib/Crypt/Mode/OFB.pm b/lib/Crypt/Mode/OFB.pm index b4522b9..05449f4 100644 --- a/lib/Crypt/Mode/OFB.pm +++ b/lib/Crypt/Mode/OFB.pm @@ -4,7 +4,7 @@ use strict; use warnings; -our $VERSION = '0.066'; +our $VERSION = '0.067'; use Crypt::Cipher; diff --git a/lib/Crypt/Mode.pm b/lib/Crypt/Mode.pm index 5e99c5b..12fb38b 100644 --- a/lib/Crypt/Mode.pm +++ b/lib/Crypt/Mode.pm @@ -2,7 +2,7 @@ use strict; use warnings; -our $VERSION = '0.066'; +our $VERSION = '0.067'; ### not used diff --git a/lib/Crypt/PK/DH.pm b/lib/Crypt/PK/DH.pm index aaf7a56..30d4f6b 100644 --- a/lib/Crypt/PK/DH.pm +++ b/lib/Crypt/PK/DH.pm @@ -2,9 +2,9 @@ use strict; use warnings; -our $VERSION = '0.066'; - -require Exporter; our @ISA = qw(Exporter); ### use Exporter 'import'; +our $VERSION = '0.067'; + +require Exporter; our @ISA = qw(Exporter); ### use Exporter 5.57 'import'; our %EXPORT_TAGS = ( all => [qw( dh_shared_secret )] ); our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } ); our @EXPORT = qw(); diff --git a/lib/Crypt/PK/DSA.pm b/lib/Crypt/PK/DSA.pm index c015311..24aa1a2 100644 --- a/lib/Crypt/PK/DSA.pm +++ b/lib/Crypt/PK/DSA.pm @@ -2,9 +2,9 @@ use strict; use warnings; -our $VERSION = '0.066'; - -require Exporter; our @ISA = qw(Exporter); ### use Exporter 'import'; +our $VERSION = '0.067'; + +require Exporter; our @ISA = qw(Exporter); ### use Exporter 5.57 'import'; our %EXPORT_TAGS = ( all => [qw( dsa_encrypt dsa_decrypt dsa_sign_message dsa_verify_message dsa_sign_hash dsa_verify_hash )] ); our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } ); our @EXPORT = qw(); diff --git a/lib/Crypt/PK/ECC.pm b/lib/Crypt/PK/ECC.pm index 33b540a..a4a85c6 100644 --- a/lib/Crypt/PK/ECC.pm +++ b/lib/Crypt/PK/ECC.pm @@ -2,9 +2,9 @@ use strict; use warnings; -our $VERSION = '0.066'; - -require Exporter; our @ISA = qw(Exporter); ### use Exporter 'import'; +our $VERSION = '0.067'; + +require Exporter; our @ISA = qw(Exporter); ### use Exporter 5.57 'import'; our %EXPORT_TAGS = ( all => [qw( ecc_encrypt ecc_decrypt ecc_sign_message ecc_verify_message ecc_sign_hash ecc_verify_hash ecc_shared_secret )] ); our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } ); our @EXPORT = qw(); diff --git a/lib/Crypt/PK/Ed25519.pm b/lib/Crypt/PK/Ed25519.pm new file mode 100644 index 0000000..4cf575b --- /dev/null +++ b/lib/Crypt/PK/Ed25519.pm @@ -0,0 +1,435 @@ +package Crypt::PK::Ed25519; + +use strict; +use warnings; +our $VERSION = '0.067'; + +require Exporter; our @ISA = qw(Exporter); ### use Exporter 5.57 'import'; +our %EXPORT_TAGS = ( all => [qw( )] ); +our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } ); +our @EXPORT = qw(); + +use Carp; +$Carp::Internal{(__PACKAGE__)}++; +use CryptX; +use Crypt::PK; +use Crypt::Misc qw(read_rawfile encode_b64u decode_b64u encode_b64 decode_b64 pem_to_der der_to_pem); + +sub new { + my $self = shift->_new(); + return @_ > 0 ? $self->import_key(@_) : $self; +} + +sub import_key_raw { + my ($self, $key, $type) = @_; + croak "FATAL: undefined key" unless $key; + croak "FATAL: invalid key" unless length($key) == 32; + croak "FATAL: undefined type" unless $type; + return $self->_import_raw($key, 1) if $type eq 'private'; + return $self->_import_raw($key, 0) if $type eq 'public'; + croak "FATAL: invalid key type '$type'"; +} + +sub import_key { + my ($self, $key, $password) = @_; + local $SIG{__DIE__} = \&CryptX::_croak; + croak "FATAL: undefined key" unless $key; + + # special case + if (ref($key) eq 'HASH') { + if ($key->{kty} && $key->{kty} eq "OKP" && $key->{crv} && $key->{crv} eq 'Ed25519') { + # JWK-like structure e.g. + # {"kty":"OKP","crv":"Ed25519","d":"...","x":"..."} + return $self->_import_raw(decode_b64u($key->{d}), 1) if $key->{d}; # private + return $self->_import_raw(decode_b64u($key->{x}), 0) if $key->{x}; # public + } + if ($key->{curve} && $key->{curve} eq "ed25519" && ($key->{priv} || $key->{pub})) { + # hash exported via key2hash + return $self->_import_raw(pack("H*", $key->{priv}), 1) if $key->{priv}; + return $self->_import_raw(pack("H*", $key->{pub}), 0) if $key->{pub}; + } + croak "FATAL: unexpected Ed25519 key hash"; + } + + my $data; + if (ref($key) eq 'SCALAR') { + $data = $$key; + } + elsif (-f $key) { + $data = read_rawfile($key); + } + else { + croak "FATAL: non-existing file '$key'"; + } + croak "FATAL: invalid key data" unless $data; + + if ($data =~ /-----BEGIN PUBLIC KEY-----(.*?)-----END/sg) { + $data = pem_to_der($data, $password); + return $self->_import($data); + } + elsif ($data =~ /-----BEGIN PRIVATE KEY-----(.*?)-----END/sg) { + $data = pem_to_der($data, $password); + return $self->_import_pkcs8($data, $password); + } + elsif ($data =~ /-----BEGIN ENCRYPTED PRIVATE KEY-----(.*?)-----END/sg) { + $data = pem_to_der($data, $password); + return $self->_import_pkcs8($data, $password); + } + elsif ($data =~ /-----BEGIN ED25519 PRIVATE KEY-----(.*?)-----END/sg) { + $data = pem_to_der($data, $password); + return $self->_import_pkcs8($data, $password); + } + elsif ($data =~ /^\s*(\{.*?\})\s*$/s) { # JSON + my $h = CryptX::_decode_json("$1"); + if ($h->{kty} && $h->{kty} eq "OKP" && $h->{crv} && $h->{crv} eq 'Ed25519') { + return $self->_import_raw(decode_b64u($h->{d}), 1) if $h->{d}; # private + return $self->_import_raw(decode_b64u($h->{x}), 0) if $h->{x}; # public + } + } + elsif ($data =~ /-----BEGIN CERTIFICATE-----(.*?)-----END CERTIFICATE-----/sg) { + $data = pem_to_der($data); + return $self->_import_x509($data); + } + elsif ($data =~ /-----BEGIN OPENSSH PRIVATE KEY-----(.*?)-----END/sg) { + #XXX-FIXME-TODO + # https://crypto.stackexchange.com/questions/71789/openssh-ed2215-private-key-format + # https://cvsweb.openbsd.org/src/usr.bin/ssh/PROTOCOL.key?annotate=HEAD + croak "FATAL: OPENSSH PRIVATE KEY not supported"; + } + elsif ($data =~ /---- BEGIN SSH2 PUBLIC KEY ----(.*?)---- END SSH2 PUBLIC KEY ----/sg) { + $data = pem_to_der($data); + my ($typ, $pubkey) = Crypt::PK::_ssh_parse($data); + return $self->_import_raw($pubkey, 0) if $typ eq 'ssh-ed25519' && length($pubkey) == 32; + } + elsif ($data =~ /(ssh-ed25519)\s+(\S+)/) { + $data = decode_b64("$2"); + my ($typ, $pubkey) = Crypt::PK::_ssh_parse($data); + return $self->_import_raw($pubkey, 0) if $typ eq 'ssh-ed25519' && length($pubkey) == 32; + } + elsif (length($data) == 32) { + croak "FATAL: use import_key_raw() to load raw (32 bytes) Ed25519 key"; + } + else { + my $rv = eval { $self->_import($data) } || + eval { $self->_import_pkcs8($data, $password) } || + eval { $self->_import_x509($data) }; + return $rv if $rv; + } + croak "FATAL: invalid or unsupported Ed25519 key format"; +} + +sub export_key_pem { + my ($self, $type, $password, $cipher) = @_; + local $SIG{__DIE__} = \&CryptX::_croak; + my $key = $self->export_key_der($type||''); + return unless $key; + return der_to_pem($key, "ED25519 PRIVATE KEY", $password, $cipher) if substr($type, 0, 7) eq 'private'; + return der_to_pem($key, "PUBLIC KEY") if substr($type,0, 6) eq 'public'; +} + +sub export_key_jwk { + my ($self, $type, $wanthash) = @_; + local $SIG{__DIE__} = \&CryptX::_croak; + my $kh = $self->key2hash; + return unless $kh; + my $hash = { kty => "OKP", crv => "Ed25519" }; + $hash->{x} = encode_b64u(pack("H*", $kh->{pub})); + $hash->{d} = encode_b64u(pack("H*", $kh->{priv})) if $type && $type eq 'private' && $kh->{priv}; + return $wanthash ? $hash : CryptX::_encode_json($hash); +} + +sub CLONE_SKIP { 1 } # prevent cloning + +1; + +=pod + +=head1 NAME + +Crypt::PK::Ed25519 - Digital signature based on Ed25519 + +=head1 SYNOPSIS + + use Crypt::PK::Ed25519; + + #Signature: Alice + my $priv = Crypt::PK::Ed25519->new('Alice_priv_ed25519.der'); + my $sig = $priv->sign_message($message); + + #Signature: Bob (received $message + $sig) + my $pub = Crypt::PK::Ed25519->new('Alice_pub_ed25519.der'); + $pub->verify_message($sig, $message) or die "ERROR"; + + #Load key + my $pk = Crypt::PK::Ed25519->new; + my $pk_hex = "A05D1AEA5830AC9A65CDFB384660D497E3697C46B419CF2CEC85DE8BD245459D"; + $pk->import_key_raw(pack("H*", $pk_hex), "public"); + my $sk = Crypt::PK::Ed25519->new; + my $sk_hex = "45C109BA6FD24E8B67D23EFB6B92D99CD457E2137172C0D749FE2B5A0C142DAD"; + $sk->import_key_raw(pack("H*", $sk_hex), "private"); + + #Key generation + my $pk = Crypt::PK::Ed25519->new->generate_key; + my $private_der = $pk->export_key_der('private'); + my $public_der = $pk->export_key_der('public'); + my $private_pem = $pk->export_key_pem('private'); + my $public_pem = $pk->export_key_pem('public'); + my $private_raw = $pk->export_key_raw('private'); + my $public_raw = $pk->export_key_raw('public'); + my $private_jwk = $pk->export_key_jwk('private'); + my $public_jwk = $pk->export_key_jwk('public'); + +=head1 DESCRIPTION + +I + +=head1 METHODS + +=head2 new + + my $pk = Crypt::PK::Ed25519->new(); + #or + my $pk = Crypt::PK::Ed25519->new($priv_or_pub_key_filename); + #or + my $pk = Crypt::PK::Ed25519->new(\$buffer_containing_priv_or_pub_key); + +Support for password protected PEM keys + + my $pk = Crypt::PK::Ed25519->new($priv_pem_key_filename, $password); + #or + my $pk = Crypt::PK::Ed25519->new(\$buffer_containing_priv_pem_key, $password); + +=head2 generate_key + +Uses Yarrow-based cryptographically strong random number generator seeded with +random data taken from C (UNIX) or C (Win32). + + $pk->generate_key; + +=head2 import_key + +Loads private or public key in DER or PEM format. + + $pk->import_key($filename); + #or + $pk->import_key(\$buffer_containing_key); + +Support for password protected PEM keys: + + $pk->import_key($filename, $password); + #or + $pk->import_key(\$buffer_containing_key, $password); + +Loading private or public keys form perl hash: + + $pk->import_key($hashref); + + # the $hashref is either a key exported via key2hash + $pk->import_key({ + curve => "ed25519", + pub => "A05D1AEA5830AC9A65CDFB384660D497E3697C46B419CF2CEC85DE8BD245459D", + priv => "45C109BA6FD24E8B67D23EFB6B92D99CD457E2137172C0D749FE2B5A0C142DAD", + }); + + # or a hash with items corresponding to JWK (JSON Web Key) + $pk->import_key({ + kty => "OKP", + crv => "Ed25519", + d => "RcEJum_STotn0j77a5LZnNRX4hNxcsDXSf4rWgwULa0", + x => "oF0a6lgwrJplzfs4RmDUl-NpfEa0Gc8s7IXei9JFRZ0", + }); + +Supported key formats: + + # all formats can be loaded from a file + my $pk = Crypt::PK::Ed25519->new($filename); + + # or from a buffer containing the key + my $pk = Crypt::PK::Ed25519->new(\$buffer_with_key); + +=over + +=item * Ed25519 private keys in PEM format + + -----BEGIN ED25519 PRIVATE KEY----- + MC4CAQAwBQYDK2VwBCIEIEXBCbpv0k6LZ9I++2uS2ZzUV+ITcXLA10n+K1oMFC2t + -----END ED25519 PRIVATE KEY----- + +=item * Ed25519 private keys in password protected PEM format + + -----BEGIN ED25519 PRIVATE KEY----- + Proc-Type: 4,ENCRYPTED + DEK-Info: DES-CBC,6A64D756D49C1EFF + + 8xQ7OyfQ10IITNEKcJGZA53Z1yk+NJQU7hrKqXwChZtgWNInhMBJRl9pozLKDSkH + v7u6EOve8NY= + -----END ED25519 PRIVATE KEY----- + +=item * PKCS#8 private keys + + -----BEGIN PRIVATE KEY----- + MC4CAQAwBQYDK2VwBCIEIEXBCbpv0k6LZ9I++2uS2ZzUV+ITcXLA10n+K1oMFC2t + -----END PRIVATE KEY----- + +=item * PKCS#8 encrypted private keys + + -----BEGIN ENCRYPTED PRIVATE KEY----- + MIGHMEsGCSqGSIb3DQEFDTA+MCkGCSqGSIb3DQEFDDAcBAjPx9JkdpRH2QICCAAw + DAYIKoZIhvcNAgkFADARBgUrDgMCBwQIWWieQojaWTcEOGj43SxqHUys4Eb2M27N + AkhqpmhosOxKrpGi0L3h8m8ipHE8EwI94NeOMsjfVw60aJuCrssY5vKN + -----END ENCRYPTED PRIVATE KEY----- + +=item * Ed25519 public keys in PEM format + + -----BEGIN PUBLIC KEY----- + MCowBQYDK2VwAyEAoF0a6lgwrJplzfs4RmDUl+NpfEa0Gc8s7IXei9JFRZ0= + -----END PUBLIC KEY----- + +=item * Ed25519 public key from X509 certificate + + -----BEGIN CERTIFICATE----- + MIIBODCB66ADAgECAhRWDU9FZBBUZ7KTdX8f7Bco8jsoaTAFBgMrZXAwETEPMA0G + A1UEAwwGQ3J5cHRYMCAXDTIwMDExOTEzMDIwMloYDzIyOTMxMTAyMTMwMjAyWjAR + MQ8wDQYDVQQDDAZDcnlwdFgwKjAFBgMrZXADIQCgXRrqWDCsmmXN+zhGYNSX42l8 + RrQZzyzshd6L0kVFnaNTMFEwHQYDVR0OBBYEFHCGFtVibAxxWYyRt5wazMpqSZDV + MB8GA1UdIwQYMBaAFHCGFtVibAxxWYyRt5wazMpqSZDVMA8GA1UdEwEB/wQFMAMB + Af8wBQYDK2VwA0EAqG/+98smzqF/wmFX3zHXSaA67as202HnBJod1Tiurw1f+lr3 + BX6OMtsDpgRq9O77IF1Qyx/MdJEwwErczOIbAA== + -----END CERTIFICATE----- + +=item * SSH public Ed25519 keys + + ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIL0XsiFcRDp6Hpsoak8OdiiBMJhM2UKszNTxoGS7dJ++ + +=item * SSH public Ed25519 keys (RFC-4716 format) + + ---- BEGIN SSH2 PUBLIC KEY ---- + Comment: "256-bit ED25519, converted from OpenSSH" + AAAAC3NzaC1lZDI1NTE5AAAAIL0XsiFcRDp6Hpsoak8OdiiBMJhM2UKszNTxoGS7dJ++ + ---- END SSH2 PUBLIC KEY ---- + +=item * Ed25519 private keys in JSON Web Key (JWK) format + +See L + + { + "kty":"OKP", + "crv":"Ed25519", + "x":"oF0a6lgwrJplzfs4RmDUl-NpfEa0Gc8s7IXei9JFRZ0", + "d":"RcEJum_STotn0j77a5LZnNRX4hNxcsDXSf4rWgwULa0", + } + +B For JWK support you need to have L, L or L module. + +=item * Ed25519 public keys in JSON Web Key (JWK) format + + { + "kty":"OKP", + "crv":"Ed25519", + "x":"oF0a6lgwrJplzfs4RmDUl-NpfEa0Gc8s7IXei9JFRZ0", + } + +B For JWK support you need to have L, L or L module. + +=back + +=head2 import_key_raw + +Import raw public/private key - can load raw key data exported by L. + + $pk->import_key_raw($key, 'public'); + $pk->import_key_raw($key, 'private'); + +=head2 export_key_der + + my $private_der = $pk->export_key_der('private'); + #or + my $public_der = $pk->export_key_der('public'); + +=head2 export_key_pem + + my $private_pem = $pk->export_key_pem('private'); + #or + my $public_pem = $pk->export_key_pem('public'); + +Support for password protected PEM keys + + my $private_pem = $pk->export_key_pem('private', $password); + #or + my $private_pem = $pk->export_key_pem('private', $password, $cipher); + + # supported ciphers: 'DES-CBC' + # 'DES-EDE3-CBC' + # 'SEED-CBC' + # 'CAMELLIA-128-CBC' + # 'CAMELLIA-192-CBC' + # 'CAMELLIA-256-CBC' + # 'AES-128-CBC' + # 'AES-192-CBC' + # 'AES-256-CBC' (DEFAULT) + +=head2 export_key_jwk + +Exports public/private keys as a JSON Web Key (JWK). + + my $private_json_text = $pk->export_key_jwk('private'); + #or + my $public_json_text = $pk->export_key_jwk('public'); + +Also exports public/private keys as a perl HASH with JWK structure. + + my $jwk_hash = $pk->export_key_jwk('private', 1); + #or + my $jwk_hash = $pk->export_key_jwk('public', 1); + +B For JWK support you need to have L, L or L module. + +=head2 export_key_raw + +Export raw public/private key + + my $private_bytes = $pk->export_key_raw('private'); + #or + my $public_bytes = $pk->export_key_raw('public'); + +=head2 sign_message + + my $signature = $priv->sign_message($message); + +=head2 verify_message + + my $valid = $pub->verify_message($signature, $message) + +=head2 is_private + + my $rv = $pk->is_private; + # 1 .. private key loaded + # 0 .. public key loaded + # undef .. no key loaded + +=head2 key2hash + + my $hash = $pk->key2hash; + + # returns hash like this (or undef if no key loaded): + { + curve => "ed25519", + # raw public key as a hexadecimal string + pub => "A05D1AEA5830AC9A65CDFB384660D497E3697C46B419CF2CEC85DE8BD245459D", + # raw private key as a hexadecimal string. undef if key is public only + priv => "45C109BA6FD24E8B67D23EFB6B92D99CD457E2137172C0D749FE2B5A0C142DAD", + } + +=head1 SEE ALSO + +=over + +=item * L + +=item * L + +=item * L + +=back + +=cut diff --git a/lib/Crypt/PK/RSA.pm b/lib/Crypt/PK/RSA.pm index e86ae64..51ce845 100644 --- a/lib/Crypt/PK/RSA.pm +++ b/lib/Crypt/PK/RSA.pm @@ -2,9 +2,9 @@ use strict; use warnings; -our $VERSION = '0.066'; - -require Exporter; our @ISA = qw(Exporter); ### use Exporter 'import'; +our $VERSION = '0.067'; + +require Exporter; our @ISA = qw(Exporter); ### use Exporter 5.57 'import'; our %EXPORT_TAGS = ( all => [qw(rsa_encrypt rsa_decrypt rsa_sign_message rsa_verify_message rsa_sign_hash rsa_verify_hash)] ); our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } ); our @EXPORT = qw(); diff --git a/lib/Crypt/PK/X25519.pm b/lib/Crypt/PK/X25519.pm new file mode 100644 index 0000000..bc01310 --- /dev/null +++ b/lib/Crypt/PK/X25519.pm @@ -0,0 +1,391 @@ +package Crypt::PK::X25519; + +use strict; +use warnings; +our $VERSION = '0.067'; + +require Exporter; our @ISA = qw(Exporter); ### use Exporter 5.57 'import'; +our %EXPORT_TAGS = ( all => [qw( )] ); +our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } ); +our @EXPORT = qw(); + +use Carp; +$Carp::Internal{(__PACKAGE__)}++; +use CryptX; +use Crypt::PK; +use Crypt::Misc qw(read_rawfile encode_b64u decode_b64u encode_b64 decode_b64 pem_to_der der_to_pem); + +sub new { + my $self = shift->_new(); + return @_ > 0 ? $self->import_key(@_) : $self; +} + +sub import_key_raw { + my ($self, $key, $type) = @_; + croak "FATAL: undefined key" unless $key; + croak "FATAL: invalid key" unless length($key) == 32; + croak "FATAL: undefined type" unless $type; + return $self->_import_raw($key, 1) if $type eq 'private'; + return $self->_import_raw($key, 0) if $type eq 'public'; + croak "FATAL: invalid key type '$type'"; +} + +sub import_key { + my ($self, $key, $password) = @_; + local $SIG{__DIE__} = \&CryptX::_croak; + croak "FATAL: undefined key" unless $key; + + # special case + if (ref($key) eq 'HASH') { + if ($key->{kty} && $key->{kty} eq "OKP" && $key->{crv} && $key->{crv} eq 'X25519') { + # JWK-like structure e.g. + # {"kty":"OKP","crv":"X25519","d":"...","x":"..."} + return $self->_import_raw(decode_b64u($key->{d}), 1) if $key->{d}; # private + return $self->_import_raw(decode_b64u($key->{x}), 0) if $key->{x}; # public + } + if ($key->{curve} && $key->{curve} eq "x25519" && ($key->{priv} || $key->{pub})) { + # hash exported via key2hash + return $self->_import_raw(pack("H*", $key->{priv}), 1) if $key->{priv}; + return $self->_import_raw(pack("H*", $key->{pub}), 0) if $key->{pub}; + } + croak "FATAL: unexpected X25519 key hash"; + } + + my $data; + if (ref($key) eq 'SCALAR') { + $data = $$key; + } + elsif (-f $key) { + $data = read_rawfile($key); + } + else { + croak "FATAL: non-existing file '$key'"; + } + croak "FATAL: invalid key data" unless $data; + + if ($data =~ /-----BEGIN PUBLIC KEY-----(.*?)-----END/sg) { + $data = pem_to_der($data, $password); + return $self->_import($data); + } + elsif ($data =~ /-----BEGIN PRIVATE KEY-----(.*?)-----END/sg) { + $data = pem_to_der($data, $password); + return $self->_import_pkcs8($data, $password); + } + elsif ($data =~ /-----BEGIN ENCRYPTED PRIVATE KEY-----(.*?)-----END/sg) { + $data = pem_to_der($data, $password); + return $self->_import_pkcs8($data, $password); + } + elsif ($data =~ /-----BEGIN X25519 PRIVATE KEY-----(.*?)-----END/sg) { + $data = pem_to_der($data, $password); + return $self->_import_pkcs8($data, $password); + } + elsif ($data =~ /^\s*(\{.*?\})\s*$/s) { # JSON + my $h = CryptX::_decode_json("$1"); + if ($h->{kty} && $h->{kty} eq "OKP" && $h->{crv} && $h->{crv} eq 'X25519') { + return $self->_import_raw(decode_b64u($h->{d}), 1) if $h->{d}; # private + return $self->_import_raw(decode_b64u($h->{x}), 0) if $h->{x}; # public + } + } + elsif (length($data) == 32) { + croak "FATAL: use import_key_raw() to load raw (32 bytes) X25519 key"; + } + else { + my $rv = eval { $self->_import($data) } || + eval { $self->_import_pkcs8($data, $password) } || + eval { $self->_import_x509($data) }; + return $rv if $rv; + } + croak "FATAL: invalid or unsupported X25519 key format"; +} + +sub export_key_pem { + my ($self, $type, $password, $cipher) = @_; + local $SIG{__DIE__} = \&CryptX::_croak; + my $key = $self->export_key_der($type||''); + return unless $key; + return der_to_pem($key, "X25519 PRIVATE KEY", $password, $cipher) if substr($type, 0, 7) eq 'private'; + return der_to_pem($key, "PUBLIC KEY") if substr($type,0, 6) eq 'public'; +} + +sub export_key_jwk { + my ($self, $type, $wanthash) = @_; + local $SIG{__DIE__} = \&CryptX::_croak; + my $kh = $self->key2hash; + return unless $kh; + my $hash = { kty => "OKP", crv => "X25519" }; + $hash->{x} = encode_b64u(pack("H*", $kh->{pub})); + $hash->{d} = encode_b64u(pack("H*", $kh->{priv})) if $type && $type eq 'private' && $kh->{priv}; + return $wanthash ? $hash : CryptX::_encode_json($hash); +} + +sub CLONE_SKIP { 1 } # prevent cloning + +1; + +=pod + +=head1 NAME + +Crypt::PK::X25519 - Asymmetric cryptography based on X25519 + +=head1 SYNOPSIS + + use Crypt::PK::X25519; + + #Shared secret + my $priv = Crypt::PK::X25519->new('Alice_priv_x25519.der'); + my $pub = Crypt::PK::X25519->new('Bob_pub_x25519.der'); + my $shared_secret = $priv->shared_secret($pub); + + #Load key + my $pk = Crypt::PK::X25519->new; + my $pk_hex = "EA7806F721A8570512C8F6EFB4E8D620C49A529E4DF5EAA77DEC646FB1E87E41"; + $pk->import_key_raw(pack("H*", $pk_hex), "public"); + my $sk = Crypt::PK::X25519->new; + my $sk_hex = "002F93D10BA5728D8DD8E9527721DABA3261C0BB1BEFDE7B4BBDAC631D454651"; + $sk->import_key_raw(pack("H*", $sk_hex), "private"); + + #Key generation + my $pk = Crypt::PK::X25519->new->generate_key; + my $private_der = $pk->export_key_der('private'); + my $public_der = $pk->export_key_der('public'); + my $private_pem = $pk->export_key_pem('private'); + my $public_pem = $pk->export_key_pem('public'); + my $private_raw = $pk->export_key_raw('private'); + my $public_raw = $pk->export_key_raw('public'); + my $private_jwk = $pk->export_key_jwk('private'); + my $public_jwk = $pk->export_key_jwk('public'); + +=head1 DESCRIPTION + +I + +=head1 METHODS + +=head2 new + + my $pk = Crypt::PK::X25519->new(); + #or + my $pk = Crypt::PK::X25519->new($priv_or_pub_key_filename); + #or + my $pk = Crypt::PK::X25519->new(\$buffer_containing_priv_or_pub_key); + +Support for password protected PEM keys + + my $pk = Crypt::PK::X25519->new($priv_pem_key_filename, $password); + #or + my $pk = Crypt::PK::X25519->new(\$buffer_containing_priv_pem_key, $password); + +=head2 generate_key + +Uses Yarrow-based cryptographically strong random number generator seeded with +random data taken from C (UNIX) or C (Win32). + + $pk->generate_key; + +=head2 import_key + +Loads private or public key in DER or PEM format. + + $pk->import_key($filename); + #or + $pk->import_key(\$buffer_containing_key); + +Support for password protected PEM keys: + + $pk->import_key($filename, $password); + #or + $pk->import_key(\$buffer_containing_key, $password); + +Loading private or public keys form perl hash: + + $pk->import_key($hashref); + + # the $hashref is either a key exported via key2hash + $pk->import_key({ + curve => "x25519", + pub => "EA7806F721A8570512C8F6EFB4E8D620C49A529E4DF5EAA77DEC646FB1E87E41", + priv => "002F93D10BA5728D8DD8E9527721DABA3261C0BB1BEFDE7B4BBDAC631D454651", + }); + + # or a hash with items corresponding to JWK (JSON Web Key) + $pk->import_key({ + kty => "OKP", + crv => "X25519", + d => "AC-T0Qulco2N2OlSdyHaujJhwLsb7957S72sYx1FRlE", + x => "6ngG9yGoVwUSyPbvtOjWIMSaUp5N9eqnfexkb7HofkE", + }); + +Supported key formats: + + # all formats can be loaded from a file + my $pk = Crypt::PK::X25519->new($filename); + + # or from a buffer containing the key + my $pk = Crypt::PK::X25519->new(\$buffer_with_key); + +=over + +=item * X25519 private keys in PEM format + + -----BEGIN X25519 PRIVATE KEY----- + MC4CAQAwBQYDK2VuBCIEIAAvk9ELpXKNjdjpUnch2royYcC7G+/ee0u9rGMdRUZR + -----END X25519 PRIVATE KEY----- + +=item * X25519 private keys in password protected PEM format + + -----BEGIN X25519 PRIVATE KEY----- + Proc-Type: 4,ENCRYPTED + DEK-Info: DES-CBC,DEEFD3D6B714E75A + + dfFWP5bKn49aZ993NVAhQQPdFWgsTb4j8CWhRjGBVTPl6ITstAL17deBIRBwZb7h + pAyIka81Kfs= + -----END X25519 PRIVATE KEY----- + +=item * X25519 public keys in PEM format + + -----BEGIN PUBLIC KEY----- + MCowBQYDK2VuAyEA6ngG9yGoVwUSyPbvtOjWIMSaUp5N9eqnfexkb7HofkE= + -----END PUBLIC KEY----- + +=item * PKCS#8 private keys + + -----BEGIN PRIVATE KEY----- + MC4CAQAwBQYDK2VuBCIEIAAvk9ELpXKNjdjpUnch2royYcC7G+/ee0u9rGMdRUZR + -----END PRIVATE KEY----- + +=item * PKCS#8 encrypted private keys + + -----BEGIN ENCRYPTED PRIVATE KEY----- + MIGHMEsGCSqGSIb3DQEFDTA+MCkGCSqGSIb3DQEFDDAcBAiS0NOFZmjJswICCAAw + DAYIKoZIhvcNAgkFADARBgUrDgMCBwQIGd40Hdso8Y4EONSRCTrqvftl9hl3zbH9 + 2QmHF1KJ4HDMdLDRxD7EynonCw2SV7BO+XNRHzw2yONqiTybfte7nk9t + -----END ENCRYPTED PRIVATE KEY----- + +=item * X25519 private keys in JSON Web Key (JWK) format + +See L + + { + "kty":"OKP", + "crv":"X25519", + "x":"6ngG9yGoVwUSyPbvtOjWIMSaUp5N9eqnfexkb7HofkE", + "d":"AC-T0Qulco2N2OlSdyHaujJhwLsb7957S72sYx1FRlE", + } + +B For JWK support you need to have L, L or L module. + +=item * X25519 public keys in JSON Web Key (JWK) format + + { + "kty":"OKP", + "crv":"X25519", + "x":"6ngG9yGoVwUSyPbvtOjWIMSaUp5N9eqnfexkb7HofkE", + } + +B For JWK support you need to have L, L or L module. + +=back + +=head2 import_key_raw + +Import raw public/private key - can load raw key data exported by L. + + $pk->import_key_raw($key, 'public'); + $pk->import_key_raw($key, 'private'); + +=head2 export_key_der + + my $private_der = $pk->export_key_der('private'); + #or + my $public_der = $pk->export_key_der('public'); + +=head2 export_key_pem + + my $private_pem = $pk->export_key_pem('private'); + #or + my $public_pem = $pk->export_key_pem('public'); + +Support for password protected PEM keys + + my $private_pem = $pk->export_key_pem('private', $password); + #or + my $private_pem = $pk->export_key_pem('private', $password, $cipher); + + # supported ciphers: 'DES-CBC' + # 'DES-EDE3-CBC' + # 'SEED-CBC' + # 'CAMELLIA-128-CBC' + # 'CAMELLIA-192-CBC' + # 'CAMELLIA-256-CBC' + # 'AES-128-CBC' + # 'AES-192-CBC' + # 'AES-256-CBC' (DEFAULT) + +=head2 export_key_jwk + +Exports public/private keys as a JSON Web Key (JWK). + + my $private_json_text = $pk->export_key_jwk('private'); + #or + my $public_json_text = $pk->export_key_jwk('public'); + +Also exports public/private keys as a perl HASH with JWK structure. + + my $jwk_hash = $pk->export_key_jwk('private', 1); + #or + my $jwk_hash = $pk->export_key_jwk('public', 1); + +B For JWK support you need to have L, L or L module. + +=head2 export_key_raw + +Export raw public/private key + + my $private_bytes = $pk->export_key_raw('private'); + #or + my $public_bytes = $pk->export_key_raw('public'); + +=head2 shared_secret + + # Alice having her priv key $pk and Bob's public key $pkb + my $pk = Crypt::PK::X25519->new($priv_key_filename); + my $pkb = Crypt::PK::X25519->new($pub_key_filename); + my $shared_secret = $pk->shared_secret($pkb); + + # Bob having his priv key $pk and Alice's public key $pka + my $pk = Crypt::PK::X25519->new($priv_key_filename); + my $pka = Crypt::PK::X25519->new($pub_key_filename); + my $shared_secret = $pk->shared_secret($pka); # same value as computed by Alice + +=head2 is_private + + my $rv = $pk->is_private; + # 1 .. private key loaded + # 0 .. public key loaded + # undef .. no key loaded + +=head2 key2hash + + my $hash = $pk->key2hash; + + # returns hash like this (or undef if no key loaded): + { + curve => "x25519", + # raw public key as a hexadecimal string + pub => "EA7806F721A8570512C8F6EFB4E8D620C49A529E4DF5EAA77DEC646FB1E87E41", + # raw private key as a hexadecimal string. undef if key is public only + priv => "002F93D10BA5728D8DD8E9527721DABA3261C0BB1BEFDE7B4BBDAC631D454651", + } + +=head1 SEE ALSO + +=over + +=item * L + +=item * L + +=back + +=cut diff --git a/lib/Crypt/PK.pm b/lib/Crypt/PK.pm index 88fcee0..dec28ed 100644 --- a/lib/Crypt/PK.pm +++ b/lib/Crypt/PK.pm @@ -2,7 +2,7 @@ use strict; use warnings; -our $VERSION = '0.066'; +our $VERSION = '0.067'; use Carp; diff --git a/lib/Crypt/PRNG/ChaCha20.pm b/lib/Crypt/PRNG/ChaCha20.pm index 23aa984..4294ac9 100644 --- a/lib/Crypt/PRNG/ChaCha20.pm +++ b/lib/Crypt/PRNG/ChaCha20.pm @@ -2,7 +2,7 @@ use strict; use warnings; -our $VERSION = '0.066'; +our $VERSION = '0.067'; use base qw(Crypt::PRNG Exporter); our %EXPORT_TAGS = ( all => [qw(random_bytes random_bytes_hex random_bytes_b64 random_bytes_b64u random_string random_string_from rand irand)] ); diff --git a/lib/Crypt/PRNG/Fortuna.pm b/lib/Crypt/PRNG/Fortuna.pm index d3c645a..f84baae 100644 --- a/lib/Crypt/PRNG/Fortuna.pm +++ b/lib/Crypt/PRNG/Fortuna.pm @@ -2,7 +2,7 @@ use strict; use warnings; -our $VERSION = '0.066'; +our $VERSION = '0.067'; use base qw(Crypt::PRNG Exporter); our %EXPORT_TAGS = ( all => [qw(random_bytes random_bytes_hex random_bytes_b64 random_bytes_b64u random_string random_string_from rand irand)] ); diff --git a/lib/Crypt/PRNG/RC4.pm b/lib/Crypt/PRNG/RC4.pm index 1c4f7f6..2706ba4 100644 --- a/lib/Crypt/PRNG/RC4.pm +++ b/lib/Crypt/PRNG/RC4.pm @@ -2,7 +2,7 @@ use strict; use warnings; -our $VERSION = '0.066'; +our $VERSION = '0.067'; use base qw(Crypt::PRNG Exporter); our %EXPORT_TAGS = ( all => [qw(random_bytes random_bytes_hex random_bytes_b64 random_bytes_b64u random_string random_string_from rand irand)] ); diff --git a/lib/Crypt/PRNG/Sober128.pm b/lib/Crypt/PRNG/Sober128.pm index e93a36e..735b6a5 100644 --- a/lib/Crypt/PRNG/Sober128.pm +++ b/lib/Crypt/PRNG/Sober128.pm @@ -2,7 +2,7 @@ use strict; use warnings; -our $VERSION = '0.066'; +our $VERSION = '0.067'; use base qw(Crypt::PRNG Exporter); our %EXPORT_TAGS = ( all => [qw(random_bytes random_bytes_hex random_bytes_b64 random_bytes_b64u random_string random_string_from rand irand)] ); diff --git a/lib/Crypt/PRNG/Yarrow.pm b/lib/Crypt/PRNG/Yarrow.pm index fa62dbb..ca62416 100644 --- a/lib/Crypt/PRNG/Yarrow.pm +++ b/lib/Crypt/PRNG/Yarrow.pm @@ -2,7 +2,7 @@ use strict; use warnings; -our $VERSION = '0.066'; +our $VERSION = '0.067'; use base qw(Crypt::PRNG Exporter); our %EXPORT_TAGS = ( all => [qw(random_bytes random_bytes_hex random_bytes_b64 random_bytes_b64u random_string random_string_from rand irand)] ); diff --git a/lib/Crypt/PRNG.pm b/lib/Crypt/PRNG.pm index 82517cd..817c33c 100644 --- a/lib/Crypt/PRNG.pm +++ b/lib/Crypt/PRNG.pm @@ -2,9 +2,9 @@ use strict; use warnings; -our $VERSION = '0.066'; - -require Exporter; our @ISA = qw(Exporter); ### use Exporter 'import'; +our $VERSION = '0.067'; + +require Exporter; our @ISA = qw(Exporter); ### use Exporter 5.57 'import'; our %EXPORT_TAGS = ( all => [qw(random_bytes random_bytes_hex random_bytes_b64 random_bytes_b64u random_string random_string_from rand irand)] ); our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } ); our @EXPORT = qw(); diff --git a/lib/Crypt/Stream/ChaCha.pm b/lib/Crypt/Stream/ChaCha.pm index 1e79dda..a071880 100644 --- a/lib/Crypt/Stream/ChaCha.pm +++ b/lib/Crypt/Stream/ChaCha.pm @@ -2,7 +2,7 @@ use strict; use warnings; -our $VERSION = '0.066'; +our $VERSION = '0.067'; use CryptX; diff --git a/lib/Crypt/Stream/RC4.pm b/lib/Crypt/Stream/RC4.pm index 03def61..3e25db1 100644 --- a/lib/Crypt/Stream/RC4.pm +++ b/lib/Crypt/Stream/RC4.pm @@ -2,7 +2,7 @@ use strict; use warnings; -our $VERSION = '0.066'; +our $VERSION = '0.067'; use CryptX; diff --git a/lib/Crypt/Stream/Rabbit.pm b/lib/Crypt/Stream/Rabbit.pm index 2274b41..70c32de 100644 --- a/lib/Crypt/Stream/Rabbit.pm +++ b/lib/Crypt/Stream/Rabbit.pm @@ -2,7 +2,7 @@ use strict; use warnings; -our $VERSION = '0.066'; +our $VERSION = '0.067'; use CryptX; diff --git a/lib/Crypt/Stream/Salsa20.pm b/lib/Crypt/Stream/Salsa20.pm index f0c9da3..4aff7ba 100644 --- a/lib/Crypt/Stream/Salsa20.pm +++ b/lib/Crypt/Stream/Salsa20.pm @@ -2,7 +2,7 @@ use strict; use warnings; -our $VERSION = '0.066'; +our $VERSION = '0.067'; use CryptX; diff --git a/lib/Crypt/Stream/Sober128.pm b/lib/Crypt/Stream/Sober128.pm index 9969ec7..c25d753 100644 --- a/lib/Crypt/Stream/Sober128.pm +++ b/lib/Crypt/Stream/Sober128.pm @@ -2,7 +2,7 @@ use strict; use warnings; -our $VERSION = '0.066'; +our $VERSION = '0.067'; use CryptX; diff --git a/lib/Crypt/Stream/Sosemanuk.pm b/lib/Crypt/Stream/Sosemanuk.pm index 373a12c..665fc95 100644 --- a/lib/Crypt/Stream/Sosemanuk.pm +++ b/lib/Crypt/Stream/Sosemanuk.pm @@ -2,7 +2,7 @@ use strict; use warnings; -our $VERSION = '0.066'; +our $VERSION = '0.067'; use CryptX; diff --git a/lib/CryptX.pm b/lib/CryptX.pm index f411d2c..ca6bfe0 100644 --- a/lib/CryptX.pm +++ b/lib/CryptX.pm @@ -2,7 +2,7 @@ use strict; use warnings ; -our $VERSION = '0.066'; +our $VERSION = '0.067'; require XSLoader; XSLoader::load('CryptX', $VERSION); @@ -58,13 +58,11 @@ =head1 NAME -CryptX - Cryptographic toolkit (self-contained, no external libraries needed) +CryptX - Cryptographic toolkit =head1 DESCRIPTION -Cryptography in CryptX is based on L - -Available modules: +Perl modules providing a cryptography based on L library. =over @@ -110,7 +108,7 @@ =item * Public key cryptography -L, L, L, L +L, L, L, L, L, L =item * Cryptographically secure random number generators - see L and related modules @@ -132,6 +130,6 @@ =head1 COPYRIGHT -Copyright (c) 2013+ DCIT, a.s. L / Karel Miko +Copyright (c) 2013-2020 DCIT, a.s. L / Karel Miko =cut diff --git a/lib/Math/BigInt/LTM.pm b/lib/Math/BigInt/LTM.pm index c8eb9b4..6fb9df5 100644 --- a/lib/Math/BigInt/LTM.pm +++ b/lib/Math/BigInt/LTM.pm @@ -2,7 +2,7 @@ use strict; use warnings; -our $VERSION = '0.066'; +our $VERSION = '0.067'; use CryptX; use Carp; diff --git a/src/Makefile b/src/Makefile index 4f7da67..83ec021 100644 --- a/src/Makefile +++ b/src/Makefile @@ -119,8 +119,8 @@ ltc/pk/ecc/ltc_ecc_mulmod.o ltc/pk/ecc/ltc_ecc_mulmod_timing.o ltc/pk/ecc/ltc_ecc_points.o \ ltc/pk/ecc/ltc_ecc_projective_add_point.o ltc/pk/ecc/ltc_ecc_projective_dbl_point.o \ ltc/pk/ecc/ltc_ecc_verify_key.o ltc/pk/ed25519/ed25519_export.o ltc/pk/ed25519/ed25519_import.o \ -ltc/pk/ed25519/ed25519_import_pkcs8.o ltc/pk/ed25519/ed25519_import_x509.o ltc/pk/ed25519/ed25519_make_key.o \ -ltc/pk/ed25519/ed25519_set_key.o ltc/pk/ed25519/ed25519_sign.o ltc/pk/ed25519/ed25519_verify.o \ +ltc/pk/ed25519/ed25519_import_pkcs8.o ltc/pk/ed25519/ed25519_import_raw.o ltc/pk/ed25519/ed25519_import_x509.o \ +ltc/pk/ed25519/ed25519_make_key.o ltc/pk/ed25519/ed25519_sign.o ltc/pk/ed25519/ed25519_verify.o \ ltc/pk/pkcs1/pkcs_1_i2osp.o ltc/pk/pkcs1/pkcs_1_mgf1.o ltc/pk/pkcs1/pkcs_1_oaep_decode.o \ ltc/pk/pkcs1/pkcs_1_oaep_encode.o ltc/pk/pkcs1/pkcs_1_os2ip.o ltc/pk/pkcs1/pkcs_1_pss_decode.o \ 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 \ @@ -129,7 +129,7 @@ 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 \ ltc/pk/rsa/rsa_sign_hash.o ltc/pk/rsa/rsa_sign_saltlen_get.o ltc/pk/rsa/rsa_verify_hash.o \ ltc/pk/x25519/x25519_export.o ltc/pk/x25519/x25519_import.o ltc/pk/x25519/x25519_import_pkcs8.o \ -ltc/pk/x25519/x25519_import_x509.o ltc/pk/x25519/x25519_make_key.o ltc/pk/x25519/x25519_set_key.o \ +ltc/pk/x25519/x25519_import_raw.o ltc/pk/x25519/x25519_import_x509.o ltc/pk/x25519/x25519_make_key.o \ ltc/pk/x25519/x25519_shared_secret.o ltc/prngs/chacha20.o ltc/prngs/fortuna.o ltc/prngs/rc4.o \ ltc/prngs/rng_get_bytes.o ltc/prngs/rng_make_prng.o ltc/prngs/sober128.o ltc/prngs/sprng.o \ ltc/prngs/yarrow.o ltc/stream/chacha/chacha_crypt.o ltc/stream/chacha/chacha_done.o \ diff --git a/src/Makefile.nmake b/src/Makefile.nmake index 3762335..8ef804c 100644 --- a/src/Makefile.nmake +++ b/src/Makefile.nmake @@ -126,8 +126,8 @@ ltc/pk/ecc/ltc_ecc_mulmod.obj ltc/pk/ecc/ltc_ecc_mulmod_timing.obj ltc/pk/ecc/ltc_ecc_points.obj \ ltc/pk/ecc/ltc_ecc_projective_add_point.obj ltc/pk/ecc/ltc_ecc_projective_dbl_point.obj \ ltc/pk/ecc/ltc_ecc_verify_key.obj ltc/pk/ed25519/ed25519_export.obj ltc/pk/ed25519/ed25519_import.obj \ -ltc/pk/ed25519/ed25519_import_pkcs8.obj ltc/pk/ed25519/ed25519_import_x509.obj ltc/pk/ed25519/ed25519_make_key.obj \ -ltc/pk/ed25519/ed25519_set_key.obj ltc/pk/ed25519/ed25519_sign.obj ltc/pk/ed25519/ed25519_verify.obj \ +ltc/pk/ed25519/ed25519_import_pkcs8.obj ltc/pk/ed25519/ed25519_import_raw.obj ltc/pk/ed25519/ed25519_import_x509.obj \ +ltc/pk/ed25519/ed25519_make_key.obj ltc/pk/ed25519/ed25519_sign.obj ltc/pk/ed25519/ed25519_verify.obj \ ltc/pk/pkcs1/pkcs_1_i2osp.obj ltc/pk/pkcs1/pkcs_1_mgf1.obj ltc/pk/pkcs1/pkcs_1_oaep_decode.obj \ ltc/pk/pkcs1/pkcs_1_oaep_encode.obj ltc/pk/pkcs1/pkcs_1_os2ip.obj ltc/pk/pkcs1/pkcs_1_pss_decode.obj \ 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 \ @@ -136,8 +136,8 @@ ltc/pk/rsa/rsa_import_pkcs8.obj ltc/pk/rsa/rsa_import_x509.obj ltc/pk/rsa/rsa_key.obj \ 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 \ ltc/pk/rsa/rsa_verify_hash.obj ltc/pk/x25519/x25519_export.obj ltc/pk/x25519/x25519_import.obj \ -ltc/pk/x25519/x25519_import_pkcs8.obj ltc/pk/x25519/x25519_import_x509.obj ltc/pk/x25519/x25519_make_key.obj \ -ltc/pk/x25519/x25519_set_key.obj ltc/pk/x25519/x25519_shared_secret.obj ltc/prngs/chacha20.obj \ +ltc/pk/x25519/x25519_import_pkcs8.obj ltc/pk/x25519/x25519_import_raw.obj ltc/pk/x25519/x25519_import_x509.obj \ +ltc/pk/x25519/x25519_make_key.obj ltc/pk/x25519/x25519_shared_secret.obj ltc/prngs/chacha20.obj \ ltc/prngs/fortuna.obj ltc/prngs/rc4.obj ltc/prngs/rng_get_bytes.obj ltc/prngs/rng_make_prng.obj \ ltc/prngs/sober128.obj ltc/prngs/sprng.obj ltc/prngs/yarrow.obj ltc/stream/chacha/chacha_crypt.obj \ ltc/stream/chacha/chacha_done.obj ltc/stream/chacha/chacha_ivctr32.obj ltc/stream/chacha/chacha_ivctr64.obj \ diff --git a/src/ltc/headers/tomcrypt_mac.h b/src/ltc/headers/tomcrypt_mac.h index cafb9a0..4b46a38 100644 --- a/src/ltc/headers/tomcrypt_mac.h +++ b/src/ltc/headers/tomcrypt_mac.h @@ -11,7 +11,6 @@ typedef struct Hmac_state { hash_state md; int hash; - hash_state hashstate; unsigned char key[MAXBLOCKSIZE]; } hmac_state; diff --git a/src/ltc/headers/tomcrypt_pk.h b/src/ltc/headers/tomcrypt_pk.h index a58e600..050e139 100644 --- a/src/ltc/headers/tomcrypt_pk.h +++ b/src/ltc/headers/tomcrypt_pk.h @@ -349,15 +349,12 @@ /** Ed25519 Signature API */ int ed25519_make_key(prng_state *prng, int wprng, curve25519_key *key); -int ed25519_set_key(const unsigned char *sk, unsigned long sklen, - const unsigned char *pk, unsigned long pklen, - curve25519_key *key); - int ed25519_export( unsigned char *out, unsigned long *outlen, int which, const curve25519_key *key); int ed25519_import(const unsigned char *in, unsigned long inlen, curve25519_key *key); +int ed25519_import_raw(const unsigned char *in, unsigned long inlen, int which, curve25519_key *key); int ed25519_import_x509(const unsigned char *in, unsigned long inlen, curve25519_key *key); int ed25519_import_pkcs8(const unsigned char *in, unsigned long inlen, const void *pwd, unsigned long pwdlen, @@ -374,15 +371,12 @@ /** X25519 Key-Exchange API */ int x25519_make_key(prng_state *prng, int wprng, curve25519_key *key); -int x25519_set_key(const unsigned char *k, unsigned long klen, - const unsigned char *u, unsigned long ulen, - curve25519_key *key); - int x25519_export( unsigned char *out, unsigned long *outlen, int which, const curve25519_key *key); int x25519_import(const unsigned char *in, unsigned long inlen, curve25519_key *key); +int x25519_import_raw(const unsigned char *in, unsigned long inlen, int which, curve25519_key *key); int x25519_import_x509(const unsigned char *in, unsigned long inlen, curve25519_key *key); int x25519_import_pkcs8(const unsigned char *in, unsigned long inlen, const void *pwd, unsigned long pwdlen, diff --git a/src/ltc/math/ltm_desc.c b/src/ltc/math/ltm_desc.c index 432ab5b..2ff71ad 100644 --- a/src/ltc/math/ltm_desc.c +++ b/src/ltc/math/ltm_desc.c @@ -13,6 +13,9 @@ #ifdef LTM_DESC #include +#if !defined(PRIVATE_MP_WARRAY) && !defined(BN_MP_PRIME_IS_PRIME_C) +#include +#endif static const struct { mp_err mpi_code; @@ -447,11 +450,16 @@ static int isprime(void *a, int b, int *c) { int err; +#if defined(PRIVATE_MP_WARRAY) || defined(BN_MP_PRIME_IS_PRIME_C) + int res; +#else + bool res; +#endif LTC_ARGCHK(a != NULL); LTC_ARGCHK(c != NULL); b = mp_prime_rabin_miller_trials(mp_count_bits(a)); - err = mpi_to_ltc_error(mp_prime_is_prime(a, b, c)); - *c = (*c == MP_YES) ? LTC_MP_YES : LTC_MP_NO; + err = mpi_to_ltc_error(mp_prime_is_prime(a, b, &res)); + *c = res ? LTC_MP_YES : LTC_MP_NO; return err; } diff --git a/src/ltc/pk/ed25519/ed25519_import.c b/src/ltc/pk/ed25519/ed25519_import.c index e9a0592..069bd24 100644 --- a/src/ltc/pk/ed25519/ed25519_import.c +++ b/src/ltc/pk/ed25519/ed25519_import.c @@ -10,7 +10,7 @@ /** @file ed25519_import.c - Import a Ed25519 key from a binary packet, Steffen Jaeckel + Import a Ed25519 key from a SubjectPublicKeyInfo, Steffen Jaeckel */ #ifdef LTC_CURVE25519 diff --git a/src/ltc/pk/ed25519/ed25519_import_raw.c b/src/ltc/pk/ed25519/ed25519_import_raw.c new file mode 100644 index 0000000..b717ef1 --- /dev/null +++ b/src/ltc/pk/ed25519/ed25519_import_raw.c @@ -0,0 +1,51 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + */ +#include "tomcrypt_private.h" + +/** + @file ed25519_import_raw.c + Set the parameters of an Ed25519 key, Steffen Jaeckel +*/ + +#ifdef LTC_CURVE25519 + +/** + Set the parameters of an Ed25519 key + + @param in The key + @param inlen The length of the key + @param which Which type of key (PK_PRIVATE or PK_PUBLIC) + @param key [out] Destination of the key + @return CRYPT_OK if successful +*/ +int ed25519_import_raw(const unsigned char *in, unsigned long inlen, int which, curve25519_key *key) +{ + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(inlen == 32uL); + LTC_ARGCHK(key != NULL); + + if (which == PK_PRIVATE) { + XMEMCPY(key->priv, in, sizeof(key->priv)); + tweetnacl_crypto_sk_to_pk(key->pub, key->priv); + } else if (which == PK_PUBLIC) { + XMEMCPY(key->pub, in, sizeof(key->pub)); + } else { + return CRYPT_INVALID_ARG; + } + key->algo = PKA_ED25519; + key->type = which; + + return CRYPT_OK; +} + +#endif + +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/src/ltc/pk/ed25519/ed25519_set_key.c b/src/ltc/pk/ed25519/ed25519_set_key.c deleted file mode 100644 index de68e69..0000000 --- a/src/ltc/pk/ed25519/ed25519_set_key.c +++ /dev/null @@ -1,65 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis - * - * LibTomCrypt is a library that provides various cryptographic - * algorithms in a highly modular and flexible manner. - * - * The library is free for all purposes without any express - * guarantee it works. - */ -#include "tomcrypt_private.h" - -/** - @file ed25519_set_ku.c - Set the parameters of an Ed25519 key, Steffen Jaeckel -*/ - -#ifdef LTC_CURVE25519 - -/** - Set the parameters of an Ed25519 key - - In case sk and pk are given it is validated that pk is really the - corresponding public part of the key pair. - - @param sk The secret key - @param sklen The length of sk - @param pk The public key - @param pklen The length of pk - @param key [out] Destination of the key - @return CRYPT_OK if successful -*/ -int ed25519_set_key(const unsigned char *sk, unsigned long sklen, - const unsigned char *pk, unsigned long pklen, - curve25519_key *key) -{ - LTC_ARGCHK(key != NULL); - - if (sk != NULL) { - LTC_ARGCHK(sklen == 32uL); - XMEMCPY(key->priv, sk, sizeof(key->priv)); - tweetnacl_crypto_sk_to_pk(key->pub, key->priv); - if (pk != NULL) { - LTC_ARGCHK(pklen == 32uL); - if (XMEM_NEQ(pk, key->pub, sizeof(key->pub)) != 0) { - zeromem(key, sizeof(*key)); - return CRYPT_INVALID_ARG; - } - } - key->type = PK_PRIVATE; - } else if (pk != NULL) { - LTC_ARGCHK(pklen == 32uL); - XMEMCPY(key->pub, pk, sizeof(key->pub)); - key->type = PK_PUBLIC; - } else { - return CRYPT_INVALID_ARG; - } - key->algo = PKA_ED25519; - - return CRYPT_OK; -} - -#endif - -/* ref: $Format:%D$ */ -/* git commit: $Format:%H$ */ -/* commit time: $Format:%ai$ */ diff --git a/src/ltc/pk/x25519/x25519_import.c b/src/ltc/pk/x25519/x25519_import.c index f62b383..6518563 100644 --- a/src/ltc/pk/x25519/x25519_import.c +++ b/src/ltc/pk/x25519/x25519_import.c @@ -10,13 +10,13 @@ /** @file x25519_import.c - Import a X25519 key from a binary packet, Steffen Jaeckel + Import a X25519 key from a SubjectPublicKeyInfo, Steffen Jaeckel */ #ifdef LTC_CURVE25519 /** - Import a X25519 key from a binary packet + Import a X25519 key @param in The packet to read @param inlen The length of the input packet @param key [out] Where to import the key to @@ -29,16 +29,6 @@ LTC_ARGCHK(in != NULL); LTC_ARGCHK(key != NULL); - - /* There's only one case where the inlen is equal to the pubkey-size - * and that's a raw pubkey, so let's just do a raw import. - */ - if (inlen == sizeof(key->pub)) { - XMEMCPY(key->pub, in, sizeof(key->pub)); - key->type = PK_PUBLIC; - key->algo = PKA_X25519; - return CRYPT_OK; - } key_len = sizeof(key->pub); if ((err = x509_decode_subject_public_key_info(in, inlen, PKA_X25519, key->pub, &key_len, LTC_ASN1_EOL, NULL, 0uL)) == CRYPT_OK) { diff --git a/src/ltc/pk/x25519/x25519_import_raw.c b/src/ltc/pk/x25519/x25519_import_raw.c new file mode 100644 index 0000000..0109085 --- /dev/null +++ b/src/ltc/pk/x25519/x25519_import_raw.c @@ -0,0 +1,51 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + */ +#include "tomcrypt_private.h" + +/** + @file x25519_import_raw.c + Set the parameters of a X25519 key, Steffen Jaeckel +*/ + +#ifdef LTC_CURVE25519 + +/** + Set the parameters of a X25519 key + + @param in The key + @param inlen The length of the key + @param which Which type of key (PK_PRIVATE or PK_PUBLIC) + @param key [out] Destination of the key + @return CRYPT_OK if successful +*/ +int x25519_import_raw(const unsigned char *in, unsigned long inlen, int which, curve25519_key *key) +{ + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(inlen == 32uL); + LTC_ARGCHK(key != NULL); + + if (which == PK_PRIVATE) { + XMEMCPY(key->priv, in, sizeof(key->priv)); + tweetnacl_crypto_scalarmult_base(key->pub, key->priv); + } else if (which == PK_PUBLIC) { + XMEMCPY(key->pub, in, sizeof(key->pub)); + } else { + return CRYPT_INVALID_ARG; + } + key->algo = PKA_X25519; + key->type = which; + + return CRYPT_OK; +} + +#endif + +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/src/ltc/pk/x25519/x25519_set_key.c b/src/ltc/pk/x25519/x25519_set_key.c deleted file mode 100644 index df276e1..0000000 --- a/src/ltc/pk/x25519/x25519_set_key.c +++ /dev/null @@ -1,65 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis - * - * LibTomCrypt is a library that provides various cryptographic - * algorithms in a highly modular and flexible manner. - * - * The library is free for all purposes without any express - * guarantee it works. - */ -#include "tomcrypt_private.h" - -/** - @file x25519_set_ku.c - Set the parameters of a X25519 key, Steffen Jaeckel -*/ - -#ifdef LTC_CURVE25519 - -/** - Set the parameters of a X25519 key - - In case k and u are given it is validated that u is really the - corresponding public part of the key pair - - @param k The k value (a.k.a scalar or private part) - @param klen The length of k - @param u The u-coordinate (a.k.a public part) - @param ulen The length of u - @param key [out] Destination of the key - @return CRYPT_OK if successful -*/ -int x25519_set_key(const unsigned char *k, unsigned long klen, - const unsigned char *u, unsigned long ulen, - curve25519_key *key) -{ - LTC_ARGCHK(key != NULL); - - if (k != NULL) { - LTC_ARGCHK(klen == 32uL); - XMEMCPY(key->priv, k, sizeof(key->priv)); - tweetnacl_crypto_scalarmult_base(key->pub, key->priv); - if (u != NULL) { - LTC_ARGCHK(ulen == 32uL); - if (XMEM_NEQ(u, key->pub, sizeof(key->pub)) != 0) { - zeromem(key, sizeof(*key)); - return CRYPT_INVALID_ARG; - } - } - key->type = PK_PRIVATE; - } else if (u != NULL) { - LTC_ARGCHK(ulen == 32uL); - XMEMCPY(key->pub, u, sizeof(key->pub)); - key->type = PK_PUBLIC; - } else { - return CRYPT_INVALID_ARG; - } - key->algo = PKA_X25519; - - return CRYPT_OK; -} - -#endif - -/* ref: $Format:%D$ */ -/* git commit: $Format:%H$ */ -/* commit time: $Format:%ai$ */ diff --git a/t/001_compile.t b/t/001_compile.t index 1abc45f..6fd8695 100644 --- a/t/001_compile.t +++ b/t/001_compile.t @@ -101,6 +101,8 @@ use Crypt::PK::DSA; use Crypt::PK::ECC; use Crypt::PK::RSA; +use Crypt::PK::X25519; +use Crypt::PK::Ed25519; use Crypt::PK; use Crypt::PRNG::ChaCha20; use Crypt::PRNG::Fortuna; diff --git a/t/003_all_pm_pod.t b/t/003_all_pm_pod.t index 85771b5..2da04e9 100644 --- a/t/003_all_pm_pod.t +++ b/t/003_all_pm_pod.t @@ -6,7 +6,7 @@ plan skip_all => "set AUTHOR_MODE to enable this test (developer only!)" unless $ENV{AUTHOR_MODE}; plan skip_all => "File::Find not installed" unless eval { require File::Find }; plan skip_all => "Test::Pod not installed" unless eval { require Test::Pod }; -plan tests => 107; +plan tests => 109; my @files; File::Find::find({ wanted=>sub { push @files, $_ if /\.pm$/ }, no_chdir=>1 }, 'lib'); diff --git a/t/004_all_pm_pod_spelling.t b/t/004_all_pm_pod_spelling.t index b692782..12bb5a5 100644 --- a/t/004_all_pm_pod_spelling.t +++ b/t/004_all_pm_pod_spelling.t @@ -22,7 +22,7 @@ }, ); -plan tests => 107; +plan tests => 109; my @files; File::Find::find({ wanted=>sub { push @files, $_ if /\.pm$/ }, no_chdir=>1 }, 'lib'); diff --git a/t/005_all_pm_pod_coverage.t b/t/005_all_pm_pod_coverage.t index f922b23..c35fbda 100644 --- a/t/005_all_pm_pod_coverage.t +++ b/t/005_all_pm_pod_coverage.t @@ -6,7 +6,7 @@ plan skip_all => "set AUTHOR_MODE to enable this test (developer only!)" unless $ENV{AUTHOR_MODE}; plan skip_all => "Pod::Coverage not installed" unless eval { require Pod::Coverage }; plan skip_all => "File::Find not installed" unless eval { require File::Find }; -plan tests => 107; +plan tests => 109; my @files; File::Find::find({ wanted=>sub { push @files, $_ if /\.pm$/ }, no_chdir=>1 }, 'lib'); diff --git a/t/data/info.txt b/t/data/info.txt new file mode 100644 index 0000000..18f9452 --- /dev/null +++ b/t/data/info.txt @@ -0,0 +1,27 @@ +openssl genpkey -algorithm x25519 -out openssl_x25519_sk.pem +openssl pkey -in openssl_x25519_sk.pem -text +openssl pkey -in openssl_x25519_sk.pem -inform PEM -out openssl_x25519_sk.der -outform DER +openssl pkey -in openssl_x25519_sk.pem -inform PEM -out openssl_x25519_sk_t.pem -traditional -outform PEM +openssl pkey -in openssl_x25519_sk.pem -inform PEM -out openssl_x25519_sk_pw.pem -outform PEM -des -passout pass:secret +openssl pkey -in openssl_x25519_sk.pem -inform PEM -out openssl_x25519_sk_pw_t.pem -traditional -outform PEM -des -passout pass:secret +openssl pkey -in openssl_x25519_sk.pem -inform PEM -out openssl_x25519_pk.der -pubout -outform DER +openssl pkey -in openssl_x25519_sk.pem -inform PEM -out openssl_x25519_pk.pem -pubout -outform PEM +openssl pkcs8 -topk8 -inform PEM -outform DER -in openssl_x25519_sk.pem -out openssl_x25519_sk.pkcs8 -nocrypt +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 +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 + + +openssl genpkey -algorithm Ed25519 -out openssl_ed25519_sk.pem +openssl pkey -in openssl_ed25519_sk.pem -text +openssl pkey -in openssl_ed25519_sk.pem -inform PEM -out openssl_ed25519_sk.der -outform DER +openssl pkey -in openssl_ed25519_sk.pem -inform PEM -out openssl_ed25519_sk_t.pem -traditional -outform PEM +openssl pkey -in openssl_ed25519_sk.pem -inform PEM -out openssl_ed25519_sk_pw.pem -outform PEM -des -passout pass:secret +openssl pkey -in openssl_ed25519_sk.pem -inform PEM -out openssl_ed25519_sk_pw_t.pem -traditional -outform PEM -des -passout pass:secret +openssl pkey -in openssl_ed25519_sk.pem -inform PEM -out openssl_ed25519_pk.der -pubout -outform DER +openssl pkey -in openssl_ed25519_sk.pem -inform PEM -out openssl_ed25519_pk.pem -pubout -outform PEM +openssl pkcs8 -topk8 -inform PEM -outform DER -in openssl_ed25519_sk.pem -out openssl_ed25519_sk.pkcs8 -nocrypt +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 +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 +openssl req -x509 -days 99999 -nodes -subj /CN=CryptX -key openssl_ed25519_sk.pem -out openssl_ed25519_x509.pem +openssl x509 -in openssl_ed25519_x509.pem -outform der -out openssl_ed25519_x509.der +openssl x509 -in openssl_ed25519_x509.pem -text diff --git a/t/data/jwk_ed25519-priv1.json b/t/data/jwk_ed25519-priv1.json new file mode 100644 index 0000000..fb7785c --- /dev/null +++ b/t/data/jwk_ed25519-priv1.json @@ -0,0 +1 @@ +{"kty":"OKP","crv":"Ed25519","x":"oF0a6lgwrJplzfs4RmDUl-NpfEa0Gc8s7IXei9JFRZ0","d":"RcEJum_STotn0j77a5LZnNRX4hNxcsDXSf4rWgwULa0"} \ No newline at end of file diff --git a/t/data/jwk_ed25519-pub1.json b/t/data/jwk_ed25519-pub1.json new file mode 100644 index 0000000..ae0a665 --- /dev/null +++ b/t/data/jwk_ed25519-pub1.json @@ -0,0 +1 @@ +{"kty":"OKP","crv":"Ed25519","x":"oF0a6lgwrJplzfs4RmDUl-NpfEa0Gc8s7IXei9JFRZ0"} \ No newline at end of file diff --git a/t/data/jwk_x25519-priv1.json b/t/data/jwk_x25519-priv1.json new file mode 100644 index 0000000..8fc5732 --- /dev/null +++ b/t/data/jwk_x25519-priv1.json @@ -0,0 +1 @@ +{"kty":"OKP","crv":"X25519","x":"6ngG9yGoVwUSyPbvtOjWIMSaUp5N9eqnfexkb7HofkE","d":"AC-T0Qulco2N2OlSdyHaujJhwLsb7957S72sYx1FRlE"} \ No newline at end of file diff --git a/t/data/jwk_x25519-pub1.json b/t/data/jwk_x25519-pub1.json new file mode 100644 index 0000000..a60eb94 --- /dev/null +++ b/t/data/jwk_x25519-pub1.json @@ -0,0 +1 @@ +{"kty":"OKP","crv":"X25519","x":"6ngG9yGoVwUSyPbvtOjWIMSaUp5N9eqnfexkb7HofkE"} \ No newline at end of file diff --git a/t/data/openssl_ed25519_pk.der b/t/data/openssl_ed25519_pk.der new file mode 100644 index 0000000..15aba90 Binary files /dev/null and b/t/data/openssl_ed25519_pk.der differ diff --git a/t/data/openssl_ed25519_pk.pem b/t/data/openssl_ed25519_pk.pem new file mode 100644 index 0000000..c44b82d --- /dev/null +++ b/t/data/openssl_ed25519_pk.pem @@ -0,0 +1,3 @@ +-----BEGIN PUBLIC KEY----- +MCowBQYDK2VwAyEAoF0a6lgwrJplzfs4RmDUl+NpfEa0Gc8s7IXei9JFRZ0= +-----END PUBLIC KEY----- diff --git a/t/data/openssl_ed25519_sk.der b/t/data/openssl_ed25519_sk.der new file mode 100644 index 0000000..1f5e935 Binary files /dev/null and b/t/data/openssl_ed25519_sk.der differ diff --git a/t/data/openssl_ed25519_sk.pem b/t/data/openssl_ed25519_sk.pem new file mode 100644 index 0000000..670cf5d --- /dev/null +++ b/t/data/openssl_ed25519_sk.pem @@ -0,0 +1,3 @@ +-----BEGIN PRIVATE KEY----- +MC4CAQAwBQYDK2VwBCIEIEXBCbpv0k6LZ9I++2uS2ZzUV+ITcXLA10n+K1oMFC2t +-----END PRIVATE KEY----- diff --git a/t/data/openssl_ed25519_sk.pkcs8 b/t/data/openssl_ed25519_sk.pkcs8 new file mode 100644 index 0000000..1f5e935 Binary files /dev/null and b/t/data/openssl_ed25519_sk.pkcs8 differ diff --git a/t/data/openssl_ed25519_sk_pbes1.pkcs8 b/t/data/openssl_ed25519_sk_pbes1.pkcs8 new file mode 100644 index 0000000..2114484 Binary files /dev/null and b/t/data/openssl_ed25519_sk_pbes1.pkcs8 differ diff --git a/t/data/openssl_ed25519_sk_pbes2.pkcs8 b/t/data/openssl_ed25519_sk_pbes2.pkcs8 new file mode 100644 index 0000000..ca0606e Binary files /dev/null and b/t/data/openssl_ed25519_sk_pbes2.pkcs8 differ diff --git a/t/data/openssl_ed25519_sk_pw.pem b/t/data/openssl_ed25519_sk_pw.pem new file mode 100644 index 0000000..9090f1e --- /dev/null +++ b/t/data/openssl_ed25519_sk_pw.pem @@ -0,0 +1,5 @@ +-----BEGIN ENCRYPTED PRIVATE KEY----- +MIGHMEsGCSqGSIb3DQEFDTA+MCkGCSqGSIb3DQEFDDAcBAjPx9JkdpRH2QICCAAw +DAYIKoZIhvcNAgkFADARBgUrDgMCBwQIWWieQojaWTcEOGj43SxqHUys4Eb2M27N +AkhqpmhosOxKrpGi0L3h8m8ipHE8EwI94NeOMsjfVw60aJuCrssY5vKN +-----END ENCRYPTED PRIVATE KEY----- diff --git a/t/data/openssl_ed25519_sk_pw_t.pem b/t/data/openssl_ed25519_sk_pw_t.pem new file mode 100644 index 0000000..31cabe0 --- /dev/null +++ b/t/data/openssl_ed25519_sk_pw_t.pem @@ -0,0 +1,7 @@ +-----BEGIN ED25519 PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-CBC,6A64D756D49C1EFF + +8xQ7OyfQ10IITNEKcJGZA53Z1yk+NJQU7hrKqXwChZtgWNInhMBJRl9pozLKDSkH +v7u6EOve8NY= +-----END ED25519 PRIVATE KEY----- diff --git a/t/data/openssl_ed25519_sk_t.pem b/t/data/openssl_ed25519_sk_t.pem new file mode 100644 index 0000000..ac8aba1 --- /dev/null +++ b/t/data/openssl_ed25519_sk_t.pem @@ -0,0 +1,3 @@ +-----BEGIN ED25519 PRIVATE KEY----- +MC4CAQAwBQYDK2VwBCIEIEXBCbpv0k6LZ9I++2uS2ZzUV+ITcXLA10n+K1oMFC2t +-----END ED25519 PRIVATE KEY----- diff --git a/t/data/openssl_ed25519_x509.der b/t/data/openssl_ed25519_x509.der new file mode 100644 index 0000000..84ae098 Binary files /dev/null and b/t/data/openssl_ed25519_x509.der differ diff --git a/t/data/openssl_ed25519_x509.pem b/t/data/openssl_ed25519_x509.pem new file mode 100644 index 0000000..771c68e --- /dev/null +++ b/t/data/openssl_ed25519_x509.pem @@ -0,0 +1,9 @@ +-----BEGIN CERTIFICATE----- +MIIBODCB66ADAgECAhRWDU9FZBBUZ7KTdX8f7Bco8jsoaTAFBgMrZXAwETEPMA0G +A1UEAwwGQ3J5cHRYMCAXDTIwMDExOTEzMDIwMloYDzIyOTMxMTAyMTMwMjAyWjAR +MQ8wDQYDVQQDDAZDcnlwdFgwKjAFBgMrZXADIQCgXRrqWDCsmmXN+zhGYNSX42l8 +RrQZzyzshd6L0kVFnaNTMFEwHQYDVR0OBBYEFHCGFtVibAxxWYyRt5wazMpqSZDV +MB8GA1UdIwQYMBaAFHCGFtVibAxxWYyRt5wazMpqSZDVMA8GA1UdEwEB/wQFMAMB +Af8wBQYDK2VwA0EAqG/+98smzqF/wmFX3zHXSaA67as202HnBJod1Tiurw1f+lr3 +BX6OMtsDpgRq9O77IF1Qyx/MdJEwwErczOIbAA== +-----END CERTIFICATE----- diff --git a/t/data/openssl_x25519_pk.der b/t/data/openssl_x25519_pk.der new file mode 100644 index 0000000..e712ef4 Binary files /dev/null and b/t/data/openssl_x25519_pk.der differ diff --git a/t/data/openssl_x25519_pk.pem b/t/data/openssl_x25519_pk.pem new file mode 100644 index 0000000..62902db --- /dev/null +++ b/t/data/openssl_x25519_pk.pem @@ -0,0 +1,3 @@ +-----BEGIN PUBLIC KEY----- +MCowBQYDK2VuAyEA6ngG9yGoVwUSyPbvtOjWIMSaUp5N9eqnfexkb7HofkE= +-----END PUBLIC KEY----- diff --git a/t/data/openssl_x25519_sk.der b/t/data/openssl_x25519_sk.der new file mode 100644 index 0000000..adfda54 Binary files /dev/null and b/t/data/openssl_x25519_sk.der differ diff --git a/t/data/openssl_x25519_sk.pem b/t/data/openssl_x25519_sk.pem new file mode 100644 index 0000000..509cc76 --- /dev/null +++ b/t/data/openssl_x25519_sk.pem @@ -0,0 +1,3 @@ +-----BEGIN PRIVATE KEY----- +MC4CAQAwBQYDK2VuBCIEIAAvk9ELpXKNjdjpUnch2royYcC7G+/ee0u9rGMdRUZR +-----END PRIVATE KEY----- diff --git a/t/data/openssl_x25519_sk.pkcs8 b/t/data/openssl_x25519_sk.pkcs8 new file mode 100644 index 0000000..adfda54 Binary files /dev/null and b/t/data/openssl_x25519_sk.pkcs8 differ diff --git a/t/data/openssl_x25519_sk_pbes1.pkcs8 b/t/data/openssl_x25519_sk_pbes1.pkcs8 new file mode 100644 index 0000000..0e76d7e Binary files /dev/null and b/t/data/openssl_x25519_sk_pbes1.pkcs8 differ diff --git a/t/data/openssl_x25519_sk_pbes2.pkcs8 b/t/data/openssl_x25519_sk_pbes2.pkcs8 new file mode 100644 index 0000000..f3bd8bf Binary files /dev/null and b/t/data/openssl_x25519_sk_pbes2.pkcs8 differ diff --git a/t/data/openssl_x25519_sk_pw.pem b/t/data/openssl_x25519_sk_pw.pem new file mode 100644 index 0000000..519f510 --- /dev/null +++ b/t/data/openssl_x25519_sk_pw.pem @@ -0,0 +1,5 @@ +-----BEGIN ENCRYPTED PRIVATE KEY----- +MIGHMEsGCSqGSIb3DQEFDTA+MCkGCSqGSIb3DQEFDDAcBAiS0NOFZmjJswICCAAw +DAYIKoZIhvcNAgkFADARBgUrDgMCBwQIGd40Hdso8Y4EONSRCTrqvftl9hl3zbH9 +2QmHF1KJ4HDMdLDRxD7EynonCw2SV7BO+XNRHzw2yONqiTybfte7nk9t +-----END ENCRYPTED PRIVATE KEY----- diff --git a/t/data/openssl_x25519_sk_pw_t.pem b/t/data/openssl_x25519_sk_pw_t.pem new file mode 100644 index 0000000..51b582f --- /dev/null +++ b/t/data/openssl_x25519_sk_pw_t.pem @@ -0,0 +1,7 @@ +-----BEGIN X25519 PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-CBC,DEEFD3D6B714E75A + +dfFWP5bKn49aZ993NVAhQQPdFWgsTb4j8CWhRjGBVTPl6ITstAL17deBIRBwZb7h +pAyIka81Kfs= +-----END X25519 PRIVATE KEY----- diff --git a/t/data/openssl_x25519_sk_t.pem b/t/data/openssl_x25519_sk_t.pem new file mode 100644 index 0000000..afed5f1 --- /dev/null +++ b/t/data/openssl_x25519_sk_t.pem @@ -0,0 +1,3 @@ +-----BEGIN X25519 PRIVATE KEY----- +MC4CAQAwBQYDK2VuBCIEIAAvk9ELpXKNjdjpUnch2royYcC7G+/ee0u9rGMdRUZR +-----END X25519 PRIVATE KEY----- diff --git a/t/data/ssh/ssh_ed25519.priv b/t/data/ssh/ssh_ed25519.priv new file mode 100644 index 0000000..92e6ef7 --- /dev/null +++ b/t/data/ssh/ssh_ed25519.priv @@ -0,0 +1,7 @@ +-----BEGIN OPENSSH PRIVATE KEY----- +b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW +QyNTUxOQAAACC9F7IhXEQ6eh6bKGpPDnYogTCYTNlCrMzU8aBku3SfvgAAAJBdUBO/XVAT +vwAAAAtzc2gtZWQyNTUxOQAAACC9F7IhXEQ6eh6bKGpPDnYogTCYTNlCrMzU8aBku3Sfvg +AAAEDVvPqQHjnRzlV/e2kq+R5egY12xCIw9mJIuVWBm05ZBL0XsiFcRDp6Hpsoak8OdiiB +MJhM2UKszNTxoGS7dJ++AAAABkNyeXB0WAECAwQFBgc= +-----END OPENSSH PRIVATE KEY----- diff --git a/t/data/ssh/ssh_ed25519.pub b/t/data/ssh/ssh_ed25519.pub new file mode 100644 index 0000000..f5b4495 --- /dev/null +++ b/t/data/ssh/ssh_ed25519.pub @@ -0,0 +1 @@ +ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIL0XsiFcRDp6Hpsoak8OdiiBMJhM2UKszNTxoGS7dJ++ CryptX diff --git a/t/data/ssh/ssh_ed25519.pub.rfc4716 b/t/data/ssh/ssh_ed25519.pub.rfc4716 new file mode 100644 index 0000000..000906e --- /dev/null +++ b/t/data/ssh/ssh_ed25519.pub.rfc4716 @@ -0,0 +1,4 @@ +---- BEGIN SSH2 PUBLIC KEY ---- +Comment: "256-bit ED25519, converted by foo@bar from OpenSSH" +AAAAC3NzaC1lZDI1NTE5AAAAIL0XsiFcRDp6Hpsoak8OdiiBMJhM2UKszNTxoGS7dJ++ +---- END SSH2 PUBLIC KEY ---- diff --git a/t/data/ssh/ssh_ed25519_pw.priv b/t/data/ssh/ssh_ed25519_pw.priv new file mode 100644 index 0000000..6ef8ae1 --- /dev/null +++ b/t/data/ssh/ssh_ed25519_pw.priv @@ -0,0 +1,8 @@ +-----BEGIN OPENSSH PRIVATE KEY----- +b3BlbnNzaC1rZXktdjEAAAAACmFlczI1Ni1jdHIAAAAGYmNyeXB0AAAAGAAAABDRI/MgFZ +zsiclU3RDp2s1hAAAAEAAAAAEAAAAzAAAAC3NzaC1lZDI1NTE5AAAAIL0XsiFcRDp6Hpso +ak8OdiiBMJhM2UKszNTxoGS7dJ++AAAAkBCS+qs8+Adk48XS6oNQermt9/wZwSbxP3po6Z +7t14DU4pYTNAMkQglqTHBgdNFpM1badmOXx0UmvIfh4BKBGg4GvJkfJl5WW2jmPnvjJhww +l3GBAcYfIVHekEXvfVaLHvo5B5JfAnFlWzEsr+3s1haXVU9eDVVVS2XSrE3O9RD2lbOdwm +S599qWbyy3nICJ1w== +-----END OPENSSH PRIVATE KEY----- diff --git a/t/pk_ed25519.t b/t/pk_ed25519.t new file mode 100644 index 0000000..b724af2 --- /dev/null +++ b/t/pk_ed25519.t @@ -0,0 +1,233 @@ +use strict; +use warnings; +use Test::More tests => 91; + +use Crypt::PK::Ed25519; +use Crypt::Misc qw(read_rawfile); + +{ + my ($k, $k2); + + # t/data/openssl_ed25519_sk.pem + # ED25519 Private-Key: + # priv = 45C109BA6FD24E8B67D23EFB6B92D99CD457E2137172C0D749FE2B5A0C142DAD == RcEJum_STotn0j77a5LZnNRX4hNxcsDXSf4rWgwULa0 + # pub = A05D1AEA5830AC9A65CDFB384660D497E3697C46B419CF2CEC85DE8BD245459D == oF0a6lgwrJplzfs4RmDUl-NpfEa0Gc8s7IXei9JFRZ0 + + my $sk_data = pack("H*", "45C109BA6FD24E8B67D23EFB6B92D99CD457E2137172C0D749FE2B5A0C142DAD"); + $k = Crypt::PK::Ed25519->new->import_key_raw($sk_data, 'private'); + ok($k, 'new+import_key_raw raw-priv'); + ok($k->is_private, 'is_private raw-priv'); + is(uc($k->key2hash->{priv}), '45C109BA6FD24E8B67D23EFB6B92D99CD457E2137172C0D749FE2B5A0C142DAD', 'key2hash->{priv} raw-priv'); + is(uc($k->key2hash->{pub}), 'A05D1AEA5830AC9A65CDFB384660D497E3697C46B419CF2CEC85DE8BD245459D', 'key2hash->{pub} raw-priv'); + is($k->export_key_raw('private'), $sk_data, 'export_key_raw private'); + + $k2 = Crypt::PK::Ed25519->new->import_key($k->key2hash); + ok($k2->is_private, 'is_private raw-priv'); + is($k->export_key_der('private'), $k2->export_key_der('private'), 'import_key hash'); + + my $pk_data = pack("H*", "A05D1AEA5830AC9A65CDFB384660D497E3697C46B419CF2CEC85DE8BD245459D"); + $k = Crypt::PK::Ed25519->new->import_key_raw($pk_data, 'public'); + ok($k, 'new+import_key_raw raw-pub'); + ok(!$k->is_private, '!is_private raw-pub'); + is(uc($k->key2hash->{pub}), 'A05D1AEA5830AC9A65CDFB384660D497E3697C46B419CF2CEC85DE8BD245459D', 'key2hash->{pub} raw-pub'); + is($k->export_key_raw('public'), $pk_data, 'export_key_raw public'); + + $k2 = Crypt::PK::Ed25519->new->import_key($k->key2hash); + ok(!$k2->is_private, 'is_private raw-priv'); + is($k->export_key_der('public'), $k2->export_key_der('public'), 'import_key hash'); + + my $sk_jwk = { kty=>"OKP",crv=>"Ed25519",d=>"RcEJum_STotn0j77a5LZnNRX4hNxcsDXSf4rWgwULa0",x=>"oF0a6lgwrJplzfs4RmDUl-NpfEa0Gc8s7IXei9JFRZ0" }; + $k = Crypt::PK::Ed25519->new($sk_jwk); + ok($k, 'new JWKHASH/priv'); + ok($k->is_private, 'is_private JWKHASH/priv'); + is(uc($k->key2hash->{priv}), '45C109BA6FD24E8B67D23EFB6B92D99CD457E2137172C0D749FE2B5A0C142DAD', 'key2hash->{priv} JWKHASH/priv'); + ok(eq_hash($sk_jwk, $k->export_key_jwk('private', 1)), 'JWKHASH export private'); + + my $pk_jwk = { kty=>"OKP",crv=>"Ed25519",x=>"oF0a6lgwrJplzfs4RmDUl-NpfEa0Gc8s7IXei9JFRZ0" }; + $k = Crypt::PK::Ed25519->new($pk_jwk); + ok($k, 'new JWKHASH/pub'); + ok(!$k->is_private, '!is_private JWKHASH/pub'); + is(uc($k->key2hash->{pub}), 'A05D1AEA5830AC9A65CDFB384660D497E3697C46B419CF2CEC85DE8BD245459D', 'key2hash->{pub} JWKHASH/pub'); + ok(eq_hash($pk_jwk, $k->export_key_jwk('public', 1)), 'JWKHASH export public'); + + $k = Crypt::PK::Ed25519->new('t/data/jwk_ed25519-priv1.json'); + ok($k, 'new JWK/priv'); + ok($k->is_private, 'is_private JWK/priv'); + is(uc($k->key2hash->{priv}), '45C109BA6FD24E8B67D23EFB6B92D99CD457E2137172C0D749FE2B5A0C142DAD', 'key2hash->{priv} JWK/priv'); + + $k = Crypt::PK::Ed25519->new('t/data/jwk_ed25519-pub1.json'); + ok($k, 'new JWK/pub'); + ok(!$k->is_private, '!is_private JWK/pub'); + is(uc($k->key2hash->{pub}), 'A05D1AEA5830AC9A65CDFB384660D497E3697C46B419CF2CEC85DE8BD245459D', 'key2hash->{pub} JWK/pub'); + + $k = Crypt::PK::Ed25519->new('t/data/openssl_ed25519_sk.der'); + ok($k, 'new openssl_ed25519_sk.der'); + ok($k->is_private, 'is_private openssl_ed25519_sk.der'); + is(uc($k->key2hash->{priv}), '45C109BA6FD24E8B67D23EFB6B92D99CD457E2137172C0D749FE2B5A0C142DAD', 'key2hash->{priv} openssl_ed25519_sk.der'); + + $k = Crypt::PK::Ed25519->new('t/data/openssl_ed25519_sk.pem'); + ok($k, 'new openssl_ed25519_sk.pem'); + ok($k->is_private, 'is_private openssl_ed25519_sk.pem'); + is(uc($k->key2hash->{priv}), '45C109BA6FD24E8B67D23EFB6B92D99CD457E2137172C0D749FE2B5A0C142DAD', 'key2hash->{priv} openssl_ed25519_sk.pem'); + + $k = Crypt::PK::Ed25519->new('t/data/openssl_ed25519_sk_t.pem'); + ok($k, 'new openssl_ed25519_sk_t.pem'); + ok($k->is_private, 'is_private openssl_ed25519_sk_t.pem'); + is(uc($k->key2hash->{priv}), '45C109BA6FD24E8B67D23EFB6B92D99CD457E2137172C0D749FE2B5A0C142DAD', 'key2hash->{priv} openssl_ed25519_sk_t.pem'); + + $k = Crypt::PK::Ed25519->new('t/data/openssl_ed25519_sk.pkcs8'); + ok($k, 'new openssl_ed25519_sk.pkcs8'); + ok($k->is_private, 'is_private openssl_ed25519_sk.pkcs8'); + is(uc($k->key2hash->{priv}), '45C109BA6FD24E8B67D23EFB6B92D99CD457E2137172C0D749FE2B5A0C142DAD', 'key2hash->{priv} openssl_ed25519_sk.pkcs8'); + + $k = Crypt::PK::Ed25519->new('t/data/openssl_ed25519_sk_pbes1.pkcs8', 'secret'); + ok($k, 'new openssl_ed25519_sk_pbes1.pkcs8'); + ok($k->is_private, 'is_private openssl_ed25519_sk_pbes1.pkcs8'); + is(uc($k->key2hash->{priv}), '45C109BA6FD24E8B67D23EFB6B92D99CD457E2137172C0D749FE2B5A0C142DAD', 'key2hash->{priv} openssl_ed25519_sk_pbes1.pkcs8'); + + $k = Crypt::PK::Ed25519->new('t/data/openssl_ed25519_sk_pbes2.pkcs8', 'secret'); + ok($k, 'new openssl_ed25519_sk_pbes2.pkcs8'); + ok($k->is_private, 'is_private openssl_ed25519_sk_pbes2.pkcs8'); + is(uc($k->key2hash->{priv}), '45C109BA6FD24E8B67D23EFB6B92D99CD457E2137172C0D749FE2B5A0C142DAD', 'key2hash->{priv} openssl_ed25519_sk_pbes2.pkcs8'); + + $k = Crypt::PK::Ed25519->new('t/data/openssl_ed25519_sk_pw.pem', 'secret'); + ok($k, 'new openssl_ed25519_sk_pw.pem'); + ok($k->is_private, 'is_private openssl_ed25519_sk_pw.pem'); + is(uc($k->key2hash->{priv}), '45C109BA6FD24E8B67D23EFB6B92D99CD457E2137172C0D749FE2B5A0C142DAD', 'key2hash->{priv} openssl_ed25519_sk_pw.pem'); + + $k = Crypt::PK::Ed25519->new('t/data/openssl_ed25519_sk_pw_t.pem', 'secret'); + ok($k, 'new openssl_ed25519_sk_pw_t.pem'); + ok($k->is_private, 'is_private openssl_ed25519_sk_pw_t.pem'); + is(uc($k->key2hash->{priv}), '45C109BA6FD24E8B67D23EFB6B92D99CD457E2137172C0D749FE2B5A0C142DAD', 'key2hash->{priv} openssl_ed25519_sk_pw_t.pem'); + + $k = Crypt::PK::Ed25519->new('t/data/openssl_ed25519_pk.pem'); + ok($k, 'new openssl_ed25519_pk.pem'); + ok(!$k->is_private, '!is_private openssl_ed25519_pk.pem'); + is(uc($k->key2hash->{pub}), 'A05D1AEA5830AC9A65CDFB384660D497E3697C46B419CF2CEC85DE8BD245459D', 'key2hash->{pub} openssl_ed25519_pk.pem'); + + $k = Crypt::PK::Ed25519->new('t/data/openssl_ed25519_x509.pem'); + ok($k, 'new openssl_ed25519_x509.pem'); + ok(!$k->is_private, '!is_private openssl_ed25519_x509.pem'); + is(uc($k->key2hash->{pub}), 'A05D1AEA5830AC9A65CDFB384660D497E3697C46B419CF2CEC85DE8BD245459D', 'key2hash->{pub} openssl_ed25519_x509.pem'); + + $k = Crypt::PK::Ed25519->new('t/data/openssl_ed25519_x509.der'); + ok($k, 'new openssl_ed25519_x509.der'); + ok(!$k->is_private, '!is_private openssl_ed25519_x509.der'); + is(uc($k->key2hash->{pub}), 'A05D1AEA5830AC9A65CDFB384660D497E3697C46B419CF2CEC85DE8BD245459D', 'key2hash->{pub} openssl_ed25519_x509.der'); + + $k = Crypt::PK::Ed25519->new('t/data/ssh/ssh_ed25519.pub'); + ok($k, 'new ssh_ed25519.pub'); + ok(!$k->is_private, '!is_private ssh_ed25519.pub'); + is(uc($k->key2hash->{pub}), 'BD17B2215C443A7A1E9B286A4F0E76288130984CD942ACCCD4F1A064BB749FBE', 'key2hash->{pub} ssh_ed25519.pub'); + + $k = Crypt::PK::Ed25519->new('t/data/ssh/ssh_ed25519.pub.rfc4716'); + ok($k, 'new ssh_ed25519.pub.rfc4716'); + ok(!$k->is_private, '!is_private ssh_ed25519.pub.rfc4716'); + is(uc($k->key2hash->{pub}), 'BD17B2215C443A7A1E9B286A4F0E76288130984CD942ACCCD4F1A064BB749FBE', 'key2hash->{pub} ssh_ed25519.pub.rfc4716'); + + ### $k = Crypt::PK::Ed25519->new('t/data/ssh/ssh_ed25519.priv'); + ### ok($k, 'new ssh_ed25519.priv'); + ### ok($k->is_private, 'is_private ssh_ed25519.priv'); + + ### $k = Crypt::PK::Ed25519->new('t/data/ssh/ssh_ed25519_pw.priv', 'secret'); + ### ok($k, 'new ssh_ed25519_pw.priv'); + ### ok($k->is_private, 'is_private ssh_ed25519_pw.priv'); +} + +{ + my $k = Crypt::PK::Ed25519->new; + $k->generate_key; + ok($k, 'generate_key'); + ok($k->is_private, 'is_private'); + ok($k->export_key_der('private'), 'export_key_der pri'); + ok($k->export_key_der('public'), 'export_key_der pub'); +} + +{ + for (qw( openssl_ed25519_pk.der openssl_ed25519_pk.pem )) { + my $k = Crypt::PK::Ed25519->new("t/data/$_"); + is($k->export_key_der('public'), read_rawfile("t/data/$_"), 'export_key_der public') if (substr($_, -3) eq "der"); + is($k->export_key_pem('public'), read_rawfile("t/data/$_"), 'export_key_pem public') if (substr($_, -3) eq "pem"); + } + + for (qw( openssl_ed25519_sk.der openssl_ed25519_sk_t.pem )) { + my $k = Crypt::PK::Ed25519->new("t/data/$_"); + is($k->export_key_der('private'), read_rawfile("t/data/$_"), 'export_key_der private') if (substr($_, -3) eq "der"); + is($k->export_key_pem('private'), read_rawfile("t/data/$_"), 'export_key_pem private') if (substr($_, -3) eq "pem"); + } +} + +{ + my $sk = Crypt::PK::Ed25519->new; + $sk->import_key('t/data/openssl_ed25519_sk.der'); + my $pk = Crypt::PK::Ed25519->new; + $pk->import_key('t/data/openssl_ed25519_pk.der'); + + my $sig = $sk->sign_message("message"); + ok(length $sig > 60, 'sign_message ' . length($sig)); + ok($pk->verify_message($sig, "message"), 'verify_message'); +} + +# test vectors from RFC 8032 +{ + my @test_vectors = ( + { + SECRETKEY => "9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60", + PUBLICKEY => "d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a", + MESSAGE => "", # 0 bytes + SIGNATURE => "e5564300c360ac729086e2cc806e828a84877f1eb8e5d974d873e065224901555fb8821590a33bacc61e39701cf9b46bd25bf5f0595bbe24655141438e7a100b", + }, + { + SECRETKEY => "4ccd089b28ff96da9db6c346ec114e0f5b8a319f35aba624da8cf6ed4fb8a6fb", + PUBLICKEY => "3d4017c3e843895a92b70aa74d1b7ebc9c982ccf2ec4968cc0cd55f12af4660c", + MESSAGE => "72", + SIGNATURE => "92a009a9f0d4cab8720e820b5f642540a2b27b5416503f8fb3762223ebdb69da085ac1e43e15996e458f3613d0f11d8c387b2eaeb4302aeeb00d291612bb0c00", + }, + { + SECRETKEY => "c5aa8df43f9f837bedb7442f31dcb7b166d38535076f094b85ce3a2e0b4458f7", + PUBLICKEY => "fc51cd8e6218a1a38da47ed00230f0580816ed13ba3303ac5deb911548908025", + MESSAGE => "af82", + SIGNATURE => "6291d657deec24024827e69c3abe01a30ce548a284743a445e3680d7db5ac3ac18ff9b538d16f290ae67f760984dc6594a7c15e9716ed28dc027beceea1ec40a", + }, + { + SECRETKEY => "f5e5767cf153319517630f226876b86c8160cc583bc013744c6bf255f5cc0ee5", + PUBLICKEY => "278117fc144c72340f67d0f2316e8386ceffbf2b2428c9c51fef7c597f1d426e", + MESSAGE => "08b8b2b733424243760fe426a4b54908632110a66c2f6591eabd3345e3e4eb98fa6e264bf09efe12ee50f8f54e9f77b1e355f6c50544e23fb1433ddf73be84d8". + "79de7c0046dc4996d9e773f4bc9efe5738829adb26c81b37c93a1b270b20329d658675fc6ea534e0810a4432826bf58c941efb65d57a338bbd2e26640f89ffbc". + "1a858efcb8550ee3a5e1998bd177e93a7363c344fe6b199ee5d02e82d522c4feba15452f80288a821a579116ec6dad2b3b310da903401aa62100ab5d1a36553e". + "06203b33890cc9b832f79ef80560ccb9a39ce767967ed628c6ad573cb116dbefefd75499da96bd68a8a97b928a8bbc103b6621fcde2beca1231d206be6cd9ec7". + "aff6f6c94fcd7204ed3455c68c83f4a41da4af2b74ef5c53f1d8ac70bdcb7ed185ce81bd84359d44254d95629e9855a94a7c1958d1f8ada5d0532ed8a5aa3fb2". + "d17ba70eb6248e594e1a2297acbbb39d502f1a8c6eb6f1ce22b3de1a1f40cc24554119a831a9aad6079cad88425de6bde1a9187ebb6092cf67bf2b13fd65f270". + "88d78b7e883c8759d2c4f5c65adb7553878ad575f9fad878e80a0c9ba63bcbcc2732e69485bbc9c90bfbd62481d9089beccf80cfe2df16a2cf65bd92dd597b07". + "07e0917af48bbb75fed413d238f5555a7a569d80c3414a8d0859dc65a46128bab27af87a71314f318c782b23ebfe808b82b0ce26401d2e22f04d83d1255dc51a". + "ddd3b75a2b1ae0784504df543af8969be3ea7082ff7fc9888c144da2af58429ec96031dbcad3dad9af0dcbaaaf268cb8fcffead94f3c7ca495e056a9b47acdb7". + "51fb73e666c6c655ade8297297d07ad1ba5e43f1bca32301651339e22904cc8c42f58c30c04aafdb038dda0847dd988dcda6f3bfd15c4b4c4525004aa06eeff8". + "ca61783aacec57fb3d1f92b0fe2fd1a85f6724517b65e614ad6808d6f6ee34dff7310fdc82aebfd904b01e1dc54b2927094b2db68d6f903b68401adebf5a7e08". + "d78ff4ef5d63653a65040cf9bfd4aca7984a74d37145986780fc0b16ac451649de6188a7dbdf191f64b5fc5e2ab47b57f7f7276cd419c17a3ca8e1b939ae49e4". + "88acba6b965610b5480109c8b17b80e1b7b750dfc7598d5d5011fd2dcc5600a32ef5b52a1ecc820e308aa342721aac0943bf6686b64b2579376504ccc493d97e". + "6aed3fb0f9cd71a43dd497f01f17c0e2cb3797aa2a2f256656168e6c496afc5fb93246f6b1116398a346f1a641f3b041e989f7914f90cc2c7fff357876e506b5". + "0d334ba77c225bc307ba537152f3f1610e4eafe595f6d9d90d11faa933a15ef1369546868a7f3a45a96768d40fd9d03412c091c6315cf4fde7cb68606937380d". + "b2eaaa707b4c4185c32eddcdd306705e4dc1ffc872eeee475a64dfac86aba41c0618983f8741c5ef68d3a101e8a3b8cac60c905c15fc910840b94c00a0b9d0", + SIGNATURE => "0aab4c900501b3e24d7cdf4663326a3a87df5e4843b2cbdb67cbf6e460fec350aa5371b1508f9f4528ecea23c436d94b5e8fcd4f681e30a6ac00a9704a188a03", + }, + { + SECRETKEY => "833fe62409237b9d62ec77587520911e9a759cec1d19755b7da901b96dca3d42", + PUBLICKEY => "ec172b93ad5e563bf4932c70e1245034c35467ef2efd4d64ebf819683467e2bf", + MESSAGE => "ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f", + SIGNATURE => "dc2a4459e7369633a52b1bf277839a00201009a3efbf3ecb69bea2186c26b58909351fc9ac90b3ecfdfbc7c66431e0303dca179c138ac17ad9bef1177331a704", + } + ); + for my $tv (@test_vectors) { + my $sk = pack("H*", $tv->{SECRETKEY}); + my $pk = pack("H*", $tv->{PUBLICKEY}); + my $msg = pack("H*", $tv->{MESSAGE}); + my $sig = pack("H*", $tv->{SIGNATURE}); + my $s = Crypt::PK::Ed25519->new->import_key_raw($sk, 'private'); + my $p = Crypt::PK::Ed25519->new->import_key_raw($pk, 'public'); + my $sigx = $s->sign_message($msg); + my $pkx = $s->export_key_raw('public'); + is(unpack("H*", $sigx), $tv->{SIGNATURE}, 'sign'); + is(unpack("H*", $pkx), $tv->{PUBLICKEY}, 'public key'); + ok($p->verify_message($sig, $msg), 'verify'); + } +} diff --git a/t/pk_x25519.t b/t/pk_x25519.t new file mode 100644 index 0000000..fd762b1 --- /dev/null +++ b/t/pk_x25519.t @@ -0,0 +1,169 @@ +use strict; +use warnings; +use Test::More tests => 69; + +use Crypt::PK::X25519; +use Crypt::Misc qw(read_rawfile); + +{ + my ($k, $k2); + + # t/data/openssl_x25519_sk.pem + # X25519 Private-Key: + # priv = 002F93D10BA5728D8DD8E9527721DABA3261C0BB1BEFDE7B4BBDAC631D454651 == AC-T0Qulco2N2OlSdyHaujJhwLsb7957S72sYx1FRlE + # pub = EA7806F721A8570512C8F6EFB4E8D620C49A529E4DF5EAA77DEC646FB1E87E41 == 6ngG9yGoVwUSyPbvtOjWIMSaUp5N9eqnfexkb7HofkE + + my $sk_data = pack("H*", "002F93D10BA5728D8DD8E9527721DABA3261C0BB1BEFDE7B4BBDAC631D454651"); + $k = Crypt::PK::X25519->new->import_key_raw($sk_data, 'private'); + ok($k, 'new+import_key_raw raw-priv'); + ok($k->is_private, 'is_private raw-priv'); + is(uc($k->key2hash->{priv}), '002F93D10BA5728D8DD8E9527721DABA3261C0BB1BEFDE7B4BBDAC631D454651', 'key2hash->{priv} raw-priv'); + is(uc($k->key2hash->{pub}), 'EA7806F721A8570512C8F6EFB4E8D620C49A529E4DF5EAA77DEC646FB1E87E41', 'key2hash->{pub} raw-priv'); + is($k->export_key_raw('private'), $sk_data, 'export_key_raw private'); + + $k2 = Crypt::PK::X25519->new->import_key($k->key2hash); + ok($k2->is_private, 'is_private raw-priv'); + is($k->export_key_der('private'), $k2->export_key_der('private'), 'import_key hash'); + + my $pk_data = pack("H*", "EA7806F721A8570512C8F6EFB4E8D620C49A529E4DF5EAA77DEC646FB1E87E41"); + $k = Crypt::PK::X25519->new->import_key_raw($pk_data, 'public'); + ok($k, 'new+import_key_raw raw-pub'); + ok(!$k->is_private, '!is_private raw-pub'); + is(uc($k->key2hash->{pub}), 'EA7806F721A8570512C8F6EFB4E8D620C49A529E4DF5EAA77DEC646FB1E87E41', 'key2hash->{pub} raw-pub'); + is($k->export_key_raw('public'), $pk_data, 'export_key_raw public'); + + $k2 = Crypt::PK::X25519->new->import_key($k->key2hash); + ok(!$k2->is_private, 'is_private raw-priv'); + is($k->export_key_der('public'), $k2->export_key_der('public'), 'import_key hash'); + + my $sk_jwk = { kty=>"OKP",crv=>"X25519",d=>"AC-T0Qulco2N2OlSdyHaujJhwLsb7957S72sYx1FRlE",x=>"6ngG9yGoVwUSyPbvtOjWIMSaUp5N9eqnfexkb7HofkE" }; + $k = Crypt::PK::X25519->new($sk_jwk); + ok($k, 'new JWKHASH/priv'); + ok($k->is_private, 'is_private JWKHASH/priv'); + is(uc($k->key2hash->{priv}), '002F93D10BA5728D8DD8E9527721DABA3261C0BB1BEFDE7B4BBDAC631D454651', 'key2hash->{priv} JWKHASH/priv'); + ok(eq_hash($sk_jwk, $k->export_key_jwk('private', 1)), 'JWKHASH export private'); + + my $pk_jwk = { kty=>"OKP",crv=>"X25519",x=>"6ngG9yGoVwUSyPbvtOjWIMSaUp5N9eqnfexkb7HofkE"}; + $k = Crypt::PK::X25519->new($pk_jwk); + ok($k, 'new JWKHASH/pub'); + ok(!$k->is_private, '!is_private JWKHASH/pub'); + is(uc($k->key2hash->{pub}), 'EA7806F721A8570512C8F6EFB4E8D620C49A529E4DF5EAA77DEC646FB1E87E41', 'key2hash->{pub} JWKHASH/pub'); + ok(eq_hash($pk_jwk, $k->export_key_jwk('public', 1)), 'JWKHASH export public'); + + $k = Crypt::PK::X25519->new('t/data/jwk_x25519-priv1.json'); + ok($k, 'new JWK/priv'); + ok($k->is_private, 'is_private JWK/priv'); + is(uc($k->key2hash->{priv}), '002F93D10BA5728D8DD8E9527721DABA3261C0BB1BEFDE7B4BBDAC631D454651', 'key2hash->{priv} JWK/priv'); + + $k = Crypt::PK::X25519->new('t/data/jwk_x25519-pub1.json'); + ok($k, 'new JWK/pub'); + ok(!$k->is_private, '!is_private JWK/pub'); + is(uc($k->key2hash->{pub}), 'EA7806F721A8570512C8F6EFB4E8D620C49A529E4DF5EAA77DEC646FB1E87E41', 'key2hash->{pub} JWK/pub'); + + $k = Crypt::PK::X25519->new('t/data/openssl_x25519_sk.der'); + ok($k, 'new openssl_x25519_sk.der'); + ok($k->is_private, 'is_private openssl_x25519_sk.der'); + is(uc($k->key2hash->{priv}), '002F93D10BA5728D8DD8E9527721DABA3261C0BB1BEFDE7B4BBDAC631D454651', 'key2hash->{priv} openssl_x25519_sk.der'); + + $k = Crypt::PK::X25519->new('t/data/openssl_x25519_sk.pem'); + ok($k, 'new openssl_x25519_sk.pem'); + ok($k->is_private, 'is_private openssl_x25519_sk.pem'); + is(uc($k->key2hash->{priv}), '002F93D10BA5728D8DD8E9527721DABA3261C0BB1BEFDE7B4BBDAC631D454651', 'key2hash->{priv} openssl_x25519_sk.pem'); + + $k = Crypt::PK::X25519->new('t/data/openssl_x25519_sk_t.pem'); + ok($k, 'new openssl_x25519_sk_t.pem'); + ok($k->is_private, 'is_private openssl_x25519_sk_t.pem'); + is(uc($k->key2hash->{priv}), '002F93D10BA5728D8DD8E9527721DABA3261C0BB1BEFDE7B4BBDAC631D454651', 'key2hash->{priv} openssl_x25519_sk_t.pem'); + + $k = Crypt::PK::X25519->new('t/data/openssl_x25519_sk.pkcs8'); + ok($k, 'new openssl_x25519_sk.pkcs8'); + ok($k->is_private, 'is_private openssl_x25519_sk.pkcs8'); + is(uc($k->key2hash->{priv}), '002F93D10BA5728D8DD8E9527721DABA3261C0BB1BEFDE7B4BBDAC631D454651', 'key2hash->{priv} openssl_x25519_sk.pkcs8'); + + $k = Crypt::PK::X25519->new('t/data/openssl_x25519_sk_pbes1.pkcs8', 'secret'); + ok($k, 'new openssl_x25519_sk_pbes1.pkcs8'); + ok($k->is_private, 'is_private openssl_x25519_sk_pbes1.pkcs8'); + is(uc($k->key2hash->{priv}), '002F93D10BA5728D8DD8E9527721DABA3261C0BB1BEFDE7B4BBDAC631D454651', 'key2hash->{priv} openssl_x25519_sk_pbes1.pkcs8'); + + $k = Crypt::PK::X25519->new('t/data/openssl_x25519_sk_pbes2.pkcs8', 'secret'); + ok($k, 'new openssl_x25519_sk_pbes2.pkcs8'); + ok($k->is_private, 'is_private openssl_x25519_sk_pbes2.pkcs8'); + is(uc($k->key2hash->{priv}), '002F93D10BA5728D8DD8E9527721DABA3261C0BB1BEFDE7B4BBDAC631D454651', 'key2hash->{priv} openssl_x25519_sk_pbes2.pkcs8'); + + $k = Crypt::PK::X25519->new('t/data/openssl_x25519_sk_pw.pem', 'secret'); + ok($k, 'new openssl_x25519_sk_pw.pem'); + ok($k->is_private, 'is_private openssl_x25519_sk_pw.pem'); + is(uc($k->key2hash->{priv}), '002F93D10BA5728D8DD8E9527721DABA3261C0BB1BEFDE7B4BBDAC631D454651', 'key2hash->{priv} openssl_x25519_sk_pw.pem'); + + $k = Crypt::PK::X25519->new('t/data/openssl_x25519_sk_pw_t.pem', 'secret'); + ok($k, 'new openssl_x25519_sk_pw_t.pem'); + ok($k->is_private, 'is_private openssl_x25519_sk_pw_t.pem'); + is(uc($k->key2hash->{priv}), '002F93D10BA5728D8DD8E9527721DABA3261C0BB1BEFDE7B4BBDAC631D454651', 'key2hash->{priv} openssl_x25519_sk_pw_t.pem'); + + $k = Crypt::PK::X25519->new('t/data/openssl_x25519_pk.pem'); + ok($k, 'new openssl_x25519_pk.pem'); + ok(!$k->is_private, '!is_private openssl_x25519_pk.pem'); + is(uc($k->key2hash->{pub}), 'EA7806F721A8570512C8F6EFB4E8D620C49A529E4DF5EAA77DEC646FB1E87E41', 'key2hash->{pub} openssl_x25519_pk.pem'); +} + +{ + my $k = Crypt::PK::X25519->new; + $k->generate_key; + ok($k, 'generate_key'); + ok($k->is_private, 'is_private'); + ok($k->export_key_der('private'), 'export_key_der pri'); + ok($k->export_key_der('public'), 'export_key_der pub'); +} + +{ + for (qw( openssl_x25519_pk.der openssl_x25519_pk.pem )) { + my $k = Crypt::PK::X25519->new("t/data/$_"); + is($k->export_key_der('public'), read_rawfile("t/data/$_"), 'export_key_der public') if (substr($_, -3) eq "der"); + is($k->export_key_pem('public'), read_rawfile("t/data/$_"), 'export_key_pem public') if (substr($_, -3) eq "pem"); + } + + for (qw( openssl_x25519_sk.der openssl_x25519_sk_t.pem )) { + my $k = Crypt::PK::X25519->new("t/data/$_"); + is($k->export_key_der('private'), read_rawfile("t/data/$_"), 'export_key_der private') if (substr($_, -3) eq "der"); + is($k->export_key_pem('private'), read_rawfile("t/data/$_"), 'export_key_pem private') if (substr($_, -3) eq "pem"); + } +} + +{ + my $sk1 = Crypt::PK::X25519->new; + $sk1->import_key('t/data/openssl_x25519_sk.der'); + my $pk1 = Crypt::PK::X25519->new->import_key_raw($sk1->export_key_raw('public'), 'public'); + ok(!$pk1->is_private, '!is_private'); + + my $sk2 = Crypt::PK::X25519->new; + $sk2->generate_key; + my $pk2 = Crypt::PK::X25519->new->import_key_raw($sk2->export_key_raw('public'), 'public'); + ok(!$pk2->is_private, '!is_private'); + + my $ss1 = $sk1->shared_secret($pk2); + my $ss2 = $sk2->shared_secret($pk1); + is(unpack("H*",$ss1), unpack("H*",$ss2), 'shared_secret'); +} + + +# rfc7748 test vectors +{ + my $sk = Crypt::PK::X25519->new->import_key_raw(pack("H*", "a546e36bf0527c9d3b16154b82465edd62144c0ac1fc5a18506a2244ba449ac4"), 'private'); + my $pk = Crypt::PK::X25519->new->import_key_raw(pack("H*", "e6db6867583030db3594c1a424b15f7c726624ec26b3353b10a903a6d0ab1c4c"), 'public'); + is(unpack("H*", $sk->shared_secret($pk)), "c3da55379de9c6908e94ea4df28d084f32eccf03491c71f754b4075577a28552"); +} +{ + my $sk = Crypt::PK::X25519->new->import_key_raw(pack("H*", "4b66e9d4d1b4673c5ad22691957d6af5c11b6421e0ea01d42ca4169e7918ba0d"), 'private'); + my $pk = Crypt::PK::X25519->new->import_key_raw(pack("H*", "e5210f12786811d3f4b7959d0538ae2c31dbe7106fc03c3efc4cd549c715a493"), 'public'); + is(unpack("H*", $sk->shared_secret($pk)), "95cbde9476e8907d7aade45cb4b873f88b595a68799fa152e6f8f7647aac7957"); +} +{ + my $sk = Crypt::PK::X25519->new->import_key_raw(pack("H*", "77076d0a7318a57d3c16c17251b26645df4c2f87ebc0992ab177fba51db92c2a"), 'private'); + my $pk = Crypt::PK::X25519->new->import_key_raw(pack("H*", "de9edb7d7b7dc1b4d35b61c2ece435373f8343c85b78674dadfc7e146f882b4f"), 'public'); + is(unpack("H*", $sk->shared_secret($pk)), "4a5d9d5ba4ce2de1728e3bf480350f25e07e21c947d19e3376f09b3c1e161742"); +} +{ + my $sk = Crypt::PK::X25519->new->import_key_raw(pack("H*", "5dab087e624a8a4b79e17f8b83800ee66f3bb1292618b6fd1c2f8b27ff88e0eb"), 'private'); + my $pk = Crypt::PK::X25519->new->import_key_raw(pack("H*", "8520f0098930a754748b7ddcb43ef75a0dbf3a0d26381af4eba4a98eaa9b4e6a"), 'public'); + is(unpack("H*", $sk->shared_secret($pk)), "4a5d9d5ba4ce2de1728e3bf480350f25e07e21c947d19e3376f09b3c1e161742"); +} diff --git a/typemap b/typemap index ef62d73..7322890 100644 --- a/typemap +++ b/typemap @@ -48,6 +48,8 @@ Crypt::PK::DSA T_PTROBJ Crypt::PK::ECC T_PTROBJ Crypt::PK::DH T_PTROBJ +Crypt::PK::Ed25519 T_PTROBJ +Crypt::PK::X25519 T_PTROBJ Math::BigInt::LTM T_PTROBJ