.\" Automatically generated by Pod::Man 4.10 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "Crypt::PK::ECC 3pm" .TH Crypt::PK::ECC 3pm "2018-12-01" "perl v5.28.1" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" Crypt::PK::ECC \- Public key cryptography based on EC .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 1 \& ### OO interface \& \& #Encryption: Alice \& my $pub = Crypt::PK::ECC\->new(\*(AqBob_pub_ecc1.der\*(Aq); \& my $ct = $pub\->encrypt("secret message"); \& # \& #Encryption: Bob (received ciphertext $ct) \& my $priv = Crypt::PK::ECC\->new(\*(AqBob_priv_ecc1.der\*(Aq); \& my $pt = $priv\->decrypt($ct); \& \& #Signature: Alice \& my $priv = Crypt::PK::ECC\->new(\*(AqAlice_priv_ecc1.der\*(Aq); \& my $sig = $priv\->sign_message($message); \& # \& #Signature: Bob (received $message + $sig) \& my $pub = Crypt::PK::ECC\->new(\*(AqAlice_pub_ecc1.der\*(Aq); \& $pub\->verify_message($sig, $message) or die "ERROR"; \& \& #Shared secret \& my $priv = Crypt::PK::ECC\->new(\*(AqAlice_priv_ecc1.der\*(Aq); \& my $pub = Crypt::PK::ECC\->new(\*(AqBob_pub_ecc1.der\*(Aq); \& my $shared_secret = $priv\->shared_secret($pub); \& \& #Key generation \& my $pk = Crypt::PK::ECC\->new(); \& $pk\->generate_key(\*(Aqsecp160r1\*(Aq); \& my $private_der = $pk\->export_key_der(\*(Aqprivate\*(Aq); \& my $public_der = $pk\->export_key_der(\*(Aqpublic\*(Aq); \& my $private_pem = $pk\->export_key_pem(\*(Aqprivate\*(Aq); \& my $public_pem = $pk\->export_key_pem(\*(Aqpublic\*(Aq); \& my $public_raw = $pk\->export_key_raw(\*(Aqpublic\*(Aq); \& \& ### Functional interface \& \& #Encryption: Alice \& my $ct = ecc_encrypt(\*(AqBob_pub_ecc1.der\*(Aq, "secret message"); \& #Encryption: Bob (received ciphertext $ct) \& my $pt = ecc_decrypt(\*(AqBob_priv_ecc1.der\*(Aq, $ct); \& \& #Signature: Alice \& my $sig = ecc_sign_message(\*(AqAlice_priv_ecc1.der\*(Aq, $message); \& #Signature: Bob (received $message + $sig) \& ecc_verify_message(\*(AqAlice_pub_ecc1.der\*(Aq, $sig, $message) or die "ERROR"; \& \& #Shared secret \& my $shared_secret = ecc_shared_secret(\*(AqAlice_priv_ecc1.der\*(Aq, \*(AqBob_pub_ecc1.der\*(Aq); .Ve .SH "DESCRIPTION" .IX Header "DESCRIPTION" The module provides a set of core \s-1ECC\s0 functions as well as implementation of \s-1ECDSA\s0 and \s-1ECDH.\s0 .PP Supports elliptic curves \f(CW\*(C`y^2 = x^3 + a*x + b\*(C'\fR over prime fields \f(CW\*(C`Fp = Z/pZ\*(C'\fR (binary fields not supported). .SH "METHODS" .IX Header "METHODS" .SS "new" .IX Subsection "new" .Vb 5 \& my $pk = Crypt::PK::ECC\->new(); \& #or \& my $pk = Crypt::PK::ECC\->new($priv_or_pub_key_filename); \& #or \& my $pk = Crypt::PK::ECC\->new(\e$buffer_containing_priv_or_pub_key); .Ve .PP Support for password protected \s-1PEM\s0 keys .PP .Vb 3 \& my $pk = Crypt::PK::ECC\->new($priv_pem_key_filename, $password); \& #or \& my $pk = Crypt::PK::ECC\->new(\e$buffer_containing_priv_pem_key, $password); .Ve .SS "generate_key" .IX Subsection "generate_key" Uses Yarrow-based cryptographically strong random number generator seeded with random data taken from \f(CW\*(C`/dev/random\*(C'\fR (\s-1UNIX\s0) or \f(CW\*(C`CryptGenRandom\*(C'\fR (Win32). .PP .Vb 3 \& $pk\->generate_key($curve_name); \& #or \& $pk\->generate_key($hashref_with_curve_params); .Ve .PP The following predefined \f(CW$curve_name\fR values are supported: .PP .Vb 10 \& # curves from http://www.ecc\-brainpool.org/download/Domain\-parameters.pdf \& \*(Aqbrainpoolp160r1\*(Aq \& \*(Aqbrainpoolp192r1\*(Aq \& \*(Aqbrainpoolp224r1\*(Aq \& \*(Aqbrainpoolp256r1\*(Aq \& \*(Aqbrainpoolp320r1\*(Aq \& \*(Aqbrainpoolp384r1\*(Aq \& \*(Aqbrainpoolp512r1\*(Aq \& # curves from http://www.secg.org/collateral/sec2_final.pdf \& \*(Aqsecp112r1\*(Aq \& \*(Aqsecp112r2\*(Aq \& \*(Aqsecp128r1\*(Aq \& \*(Aqsecp128r2\*(Aq \& \*(Aqsecp160k1\*(Aq \& \*(Aqsecp160r1\*(Aq \& \*(Aqsecp160r2\*(Aq \& \*(Aqsecp192k1\*(Aq \& \*(Aqsecp192r1\*(Aq ... same as nistp192, prime192v1 \& \*(Aqsecp224k1\*(Aq \& \*(Aqsecp224r1\*(Aq ... same as nistp224 \& \*(Aqsecp256k1\*(Aq ... used by Bitcoin \& \*(Aqsecp256r1\*(Aq ... same as nistp256, prime256v1 \& \*(Aqsecp384r1\*(Aq ... same as nistp384 \& \*(Aqsecp521r1\*(Aq ... same as nistp521 \& #curves from http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186\-4.pdf \& \*(Aqnistp192\*(Aq ... same as secp192r1, prime192v1 \& \*(Aqnistp224\*(Aq ... same as secp224r1 \& \*(Aqnistp256\*(Aq ... same as secp256r1, prime256v1 \& \*(Aqnistp384\*(Aq ... same as secp384r1 \& \*(Aqnistp521\*(Aq ... same as secp521r1 \& # curves from ANS X9.62 \& \*(Aqprime192v1\*(Aq ... same as nistp192, secp192r1 \& \*(Aqprime192v2\*(Aq \& \*(Aqprime192v3\*(Aq \& \*(Aqprime239v1\*(Aq \& \*(Aqprime239v2\*(Aq \& \*(Aqprime239v3\*(Aq \& \*(Aqprime256v1\*(Aq ... same as nistp256, secp256r1 .Ve .PP Using custom curve parameters: .PP .Vb 7 \& $pk\->generate_key({ prime => \*(AqFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF\*(Aq, \& A => \*(AqFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC\*(Aq, \& B => \*(Aq22123DC2395A05CAA7423DAECCC94760A7D462256BD56916\*(Aq, \& Gx => \*(Aq7D29778100C65A1DA1783716588DCE2B8B4AEE8E228F1896\*(Aq, \& Gy => \*(Aq38A90F22637337334B49DCB66A6DC8F9978ACA7648A943B0\*(Aq, \& order => \*(AqFFFFFFFFFFFFFFFFFFFFFFFF7A62D031C83F4294F640EC13\*(Aq, \& cofactor => 1 }); .Ve .PP See , , .SS "import_key" .IX Subsection "import_key" Loads private or public key in \s-1DER\s0 or \s-1PEM\s0 format. .PP .Vb 3 \& $pk\->import_key($filename); \& #or \& $pk\->import_key(\e$buffer_containing_key); .Ve .PP Support for password protected \s-1PEM\s0 keys: .PP .Vb 3 \& $pk\->import_key($filename, $password); \& #or \& $pk\->import_key(\e$buffer_containing_key, $password); .Ve .PP Loading private or public keys form perl hash: .PP .Vb 1 \& $pk\->import_key($hashref); \& \& # the $hashref is either a key exported via key2hash \& $pk\->import_key({ \& curve_A => "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFC", \& curve_B => "1C97BEFC54BD7A8B65ACF89F81D4D4ADC565FA45", \& curve_bits => 160, \& curve_bytes => 20, \& curve_cofactor => 1, \& curve_Gx => "4A96B5688EF573284664698968C38BB913CBFC82", \& curve_Gy => "23A628553168947D59DCC912042351377AC5FB32", \& curve_order => "0100000000000000000001F4C8F927AED3CA752257", \& curve_prime => "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFF", \& k => "B0EE84A749FE95DF997E33B8F333E12101E824C3", \& pub_x => "5AE1ACE3ED0AEA9707CE5C0BCE014F6A2F15023A", \& pub_y => "895D57E992D0A15F88D6680B27B701F615FCDC0F", \& }); \& \& # or with the curve defined just by name \& $pk\->import_key({ \& curve_name => "secp160r1", \& k => "B0EE84A749FE95DF997E33B8F333E12101E824C3", \& pub_x => "5AE1ACE3ED0AEA9707CE5C0BCE014F6A2F15023A", \& pub_y => "895D57E992D0A15F88D6680B27B701F615FCDC0F", \& }); \& \& # or a hash with items corresponding to JWK (JSON Web Key) \& $pk\->import_key({ \& kty => "EC", \& crv => "P\-256", \& x => "MKBCTNIcKUSDii11ySs3526iDZ8AiTo7Tu6KPAqv7D4", \& y => "4Etl6SRW2YiLUrN5vfvVHuhp7x8PxltmWWlbbM4IFyM", \& d => "870MB6gfuTJ4HtUnUvYMyJpr5eUZNP4Bk43bVdj3eAE", \& }); .Ve .PP Supported key formats: .PP .Vb 2 \& # all formats can be loaded from a file \& my $pk = Crypt::PK::ECC\->new($filename); \& \& # or from a buffer containing the key \& my $pk = Crypt::PK::ECC\->new(\e$buffer_with_key); .Ve .IP "\(bu" 4 \&\s-1EC\s0 private keys with with all curve parameters .Sp .Vb 10 \& \-\-\-\-\-BEGIN EC PRIVATE KEY\-\-\-\-\- \& MIIB+gIBAQQwCKEAcA6cIt6CGfyLKm57LyXWv2PgTjydrHSbvhDJTOl+7bzUW8DS \& rgSdtSPONPq1oIIBWzCCAVcCAQEwPAYHKoZIzj0BAQIxAP////////////////// \& ///////////////////////+/////wAAAAAAAAAA/////zB7BDD///////////// \& /////////////////////////////v////8AAAAAAAAAAP////wEMLMxL6fiPufk \& mI4Fa+P4LRkYHZxu/oFBEgMUCI9QE4daxlY5jYou0Z0qhcjt0+wq7wMVAKM1kmqj \& GaJ6HQCJamdzpIJ6zaxzBGEEqofKIr6LBTeOscce8yCtdG4dO2KLp5uYWfdB4IJU \& KjhVAvJdv1UpbDpUXjhydgq3NhfeSpYmLG9dnpi/kpLcKfj0Hb0omhR86doxE7Xw \& uMAKYLHOHX6BnXpDHXyQ6g5fAjEA////////////////////////////////x2NN \& gfQ3Ld9YGg2ySLCneuzsGWrMxSlzAgEBoWQDYgAEeGyHPLmHcszPQ9MIIYnznpzi \& QbvuJtYSjCqtIGxDfzgcLcc3nCc5tBxo+qX6OJEzcWdDAC0bwplY+9Z9jHR3ylNy \& ovlHoK4ItdWkVO8NH89SLSRyVuOF8N5t3CHIo93B \& \-\-\-\-\-END EC PRIVATE KEY\-\-\-\-\- .Ve .IP "\(bu" 4 \&\s-1EC\s0 private keys with curve defined by \s-1OID\s0 (short form) .Sp .Vb 5 \& \-\-\-\-\-BEGIN EC PRIVATE KEY\-\-\-\-\- \& MHcCAQEEIBG1c3z52T8XwMsahGVdOZWgKCQJfv+l7djuJjgetdbDoAoGCCqGSM49 \& AwEHoUQDQgAEoBUyo8CQAFPeYPvv78ylh5MwFZjTCLQeb042TjiMJxG+9DLFmRSM \& lBQ9T/RsLLc+PmpB1+7yPAR+oR5gZn3kJQ== \& \-\-\-\-\-END EC PRIVATE KEY\-\-\-\-\- .Ve .IP "\(bu" 4 \&\s-1EC\s0 private keys with curve defined by \s-1OID +\s0 compressed form (supported since: CryptX\-0.059) .Sp .Vb 4 \& \-\-\-\-\-BEGIN EC PRIVATE KEY\-\-\-\-\- \& MFcCAQEEIBG1c3z52T8XwMsahGVdOZWgKCQJfv+l7djuJjgetdbDoAoGCCqGSM49 \& AwEHoSQDIgADoBUyo8CQAFPeYPvv78ylh5MwFZjTCLQeb042TjiMJxE= \& \-\-\-\-\-END EC PRIVATE KEY\-\-\-\-\- .Ve .IP "\(bu" 4 \&\s-1EC\s0 private keys in password protected \s-1PEM\s0 format .Sp .Vb 3 \& \-\-\-\-\-BEGIN EC PRIVATE KEY\-\-\-\-\- \& Proc\-Type: 4,ENCRYPTED \& DEK\-Info: AES\-128\-CBC,98245C830C9282F7937E13D1D5BA11EC \& \& 0Y85oZ2+BKXYwrkBjsZdj6gnhOAfS5yDVmEsxFCDug+R3+Kw3QvyIfO4MVo9iWoA \& D7wtoRfbt2OlBaLVl553+6QrUoa2DyKf8kLHQs1x1/J7tJOMM4SCXjlrOaToQ0dT \& o7fOnjQjHne16pjgBVqGilY/I79Ab85AnE4uw7vgEucBEiU0d3nrhwuS2Opnhzyx \& 009q9VLDPwY2+q7tXjTqnk9mCmQgsiaDJqY09wlauSukYPgVuOJFmi1VdkRSDKYZ \& rUUsQvz6Q6Q+QirSlfHna+NhUgQ2eyhGszwcP6NU8iqIxI+NCwfFVuAzw539yYwS \& 8SICczoC/YRlaclayXuomQ== \& \-\-\-\-\-END EC PRIVATE KEY\-\-\-\-\- .Ve .IP "\(bu" 4 \&\s-1EC\s0 public keys with all curve parameters .Sp .Vb 8 \& \-\-\-\-\-BEGIN PUBLIC KEY\-\-\-\-\- \& MIH1MIGuBgcqhkjOPQIBMIGiAgEBMCwGByqGSM49AQECIQD///////////////// \& ///////////////////+///8LzAGBAEABAEHBEEEeb5mfvncu6xVoGKVzocLBwKb \& /NstzijZWfKBWxb4F5hIOtp3JqPEZV2k+/wOEQio/Re0SKaFVBmcR9CP+xDUuAIh \& AP////////////////////66rtzmr0igO7/SXozQNkFBAgEBA0IABITjF/nKK3jg \& pjmBRXKWAv7ekR1Ko/Nb5FFPHXjH0sDrpS7qRxFALwJHv7ylGnekgfKU3vzcewNs \& lvjpBYt0Yg4= \& \-\-\-\-\-END PUBLIC KEY\-\-\-\-\- .Ve .IP "\(bu" 4 \&\s-1EC\s0 public keys with curve defined by \s-1OID\s0 (short form) .Sp .Vb 4 \& \-\-\-\-\-BEGIN PUBLIC KEY\-\-\-\-\- \& MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEoBUyo8CQAFPeYPvv78ylh5MwFZjT \& CLQeb042TjiMJxG+9DLFmRSMlBQ9T/RsLLc+PmpB1+7yPAR+oR5gZn3kJQ== \& \-\-\-\-\-END PUBLIC KEY\-\-\-\-\- .Ve .IP "\(bu" 4 \&\s-1EC\s0 public keys with curve defined by \s-1OID +\s0 public point in compressed form (supported since: CryptX\-0.059) .Sp .Vb 4 \& \-\-\-\-\-BEGIN PUBLIC KEY\-\-\-\-\- \& MDkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDIgADoBUyo8CQAFPeYPvv78ylh5MwFZjT \& CLQeb042TjiMJxE= \& \-\-\-\-\-END PUBLIC KEY\-\-\-\-\- .Ve .IP "\(bu" 4 PKCS#8 private keys with all curve parameters .Sp .Vb 9 \& \-\-\-\-\-BEGIN PRIVATE KEY\-\-\-\-\- \& MIIBMAIBADCB0wYHKoZIzj0CATCBxwIBATAkBgcqhkjOPQEBAhkA//////////// \& /////////v//////////MEsEGP////////////////////7//////////AQYIhI9 \& wjlaBcqnQj2uzMlHYKfUYiVr1WkWAxUAxGloRDXes3jEtlypWR4qV2MFmi4EMQR9 \& KXeBAMZaHaF4NxZYjc4ri0rujiKPGJY4qQ8iY3M3M0tJ3LZqbcj5l4rKdkipQ7AC \& GQD///////////////96YtAxyD9ClPZA7BMCAQEEVTBTAgEBBBiKolTGIsTgOCtl \& 6dpdos0LvuaExCDFyT6hNAMyAAREwaCX0VY1LZxLW3G75tmft4p9uhc0J7/+NGaP \& DN3Tr7SXkT9+co2a+8KPJhQy10k= \& \-\-\-\-\-END PRIVATE KEY\-\-\-\-\- .Ve .IP "\(bu" 4 PKCS#8 private keys with curve defined by \s-1OID\s0 (short form) .Sp .Vb 5 \& \-\-\-\-\-BEGIN PRIVATE KEY\-\-\-\-\- \& MG8CAQAwEwYHKoZIzj0CAQYIKoZIzj0DAQMEVTBTAgEBBBjFP/caeQV4WO3fnWWS \& f917PGzwtypd/t+hNAMyAATSg6pBT7RO6l/p+aKcrFsGuthUdfwJWS5V3NGcVt1b \& lEHQYjWya2YnHaPq/iMFa7A= \& \-\-\-\-\-END PRIVATE KEY\-\-\-\-\- .Ve .IP "\(bu" 4 PKCS#8 encrypted private keys \- password protected keys (supported since: CryptX\-0.059) .Sp .Vb 6 \& \-\-\-\-\-BEGIN ENCRYPTED PRIVATE KEY\-\-\-\-\- \& MIGYMBwGCiqGSIb3DQEMAQMwDgQINApjTa6oFl0CAggABHi+59l4d4e6KtG9yci2 \& BSC65LEsQSnrnFAExfKptNU1zMFsDLCRvDeDQDbxc6HlfoxyqFL4SmH1g3RvC/Vv \& NfckdL5O2L8MRnM+ljkFtV2Te4fszWcJFdd7KiNOkPpn+7sWLfzQdvhHChLKUzmz \& 4INKZyMv/G7VpZ0= \& \-\-\-\-\-END ENCRYPTED PRIVATE KEY\-\-\-\-\- .Ve .IP "\(bu" 4 \&\s-1EC\s0 public key from X509 certificate .Sp .Vb 10 \& \-\-\-\-\-BEGIN CERTIFICATE\-\-\-\-\- \& MIIBdDCCARqgAwIBAgIJAL2BBClDEnnOMAoGCCqGSM49BAMEMBcxFTATBgNVBAMM \& DFRlc3QgQ2VydCBFQzAgFw0xNzEyMzAyMDMzNDFaGA8zMDE3MDUwMjIwMzM0MVow \& FzEVMBMGA1UEAwwMVGVzdCBDZXJ0IEVDMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAE \& KvkL2r5xZp7RzxLQJK+6tn/7lic+L70e1fmNbHOdxRaRvbK5G0AQWrdsbjJb92Ni \& lCQk2+w/i+VuS2Q3MSR5TaNQME4wHQYDVR0OBBYEFGbJkDyKgaMcIGHS8/WuqIVw \& +R8sMB8GA1UdIwQYMBaAFGbJkDyKgaMcIGHS8/WuqIVw+R8sMAwGA1UdEwQFMAMB \& Af8wCgYIKoZIzj0EAwQDSAAwRQIhAJtOsmrM+gJpImoynAyqTN+7myL71uxd+YeC \& 6ze4MnzWAiBQi5/BqEr/SQ1+BC2TPtswvJPRFh2ZvT/6Km3gKoNVXQ== \& \-\-\-\-\-END CERTIFICATE\-\-\-\-\- .Ve .IP "\(bu" 4 \&\s-1SSH\s0 public \s-1EC\s0 keys .Sp .Vb 1 \& ecdsa\-sha2\-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNT...T3xYfJIs= .Ve .IP "\(bu" 4 \&\s-1SSH\s0 public \s-1EC\s0 keys (\s-1RFC\-4716\s0 format) .Sp .Vb 7 \& \-\-\-\- BEGIN SSH2 PUBLIC KEY \-\-\-\- \& Comment: "521\-bit ECDSA, converted from OpenSSH" \& AAAAE2VjZHNhLXNoYTItbmlzdHA1MjEAAAAIbmlzdHA1MjEAAACFBAFk35srteP9twCwYK \& vU9ovMBi77Dd6lEBPrFaMEb0CZdZ5MC3nSqflGHRWkSbUpjdPdO7cYQNpK9YXHbNSO5hbU \& 1gFZgyiGFxwJYYz8NAjedBXMgyH4JWplK5FQm5P5cvaglItC9qkKioUXhCc67YMYBtivXl \& Ue0PgIq6kbHTqbX6+5Nw== \& \-\-\-\- END SSH2 PUBLIC KEY \-\-\-\- .Ve .IP "\(bu" 4 \&\s-1EC\s0 private keys in \s-1JSON\s0 Web Key (\s-1JWK\s0) format .Sp See .Sp .Vb 7 \& { \& "kty":"EC", \& "crv":"P\-256", \& "x":"MKBCTNIcKUSDii11ySs3526iDZ8AiTo7Tu6KPAqv7D4", \& "y":"4Etl6SRW2YiLUrN5vfvVHuhp7x8PxltmWWlbbM4IFyM", \& "d":"870MB6gfuTJ4HtUnUvYMyJpr5eUZNP4Bk43bVdj3eAE", \& } .Ve .Sp \&\fB\s-1BEWARE:\s0\fR For \s-1JWK\s0 support you need to have \s-1JSON::PP\s0, \s-1JSON::XS\s0 or Cpanel::JSON::XS module. .IP "\(bu" 4 \&\s-1EC\s0 public keys in \s-1JSON\s0 Web Key (\s-1JWK\s0) format .Sp .Vb 6 \& { \& "kty":"EC", \& "crv":"P\-256", \& "x":"MKBCTNIcKUSDii11ySs3526iDZ8AiTo7Tu6KPAqv7D4", \& "y":"4Etl6SRW2YiLUrN5vfvVHuhp7x8PxltmWWlbbM4IFyM", \& } .Ve .Sp \&\fB\s-1BEWARE:\s0\fR For \s-1JWK\s0 support you need to have \s-1JSON::PP\s0, \s-1JSON::XS\s0 or Cpanel::JSON::XS module. .SS "import_key_raw" .IX Subsection "import_key_raw" Import raw public/private key \- can load data exported by \*(L"export_key_raw\*(R". .PP .Vb 3 \& $pk\->import_key_raw($key, $curve); \& # $key .... data exported by export_key_raw() \& # $curve .. curve name or hashref with curve parameters \- same as by generate_key() .Ve .SS "export_key_der" .IX Subsection "export_key_der" .Vb 3 \& my $private_der = $pk\->export_key_der(\*(Aqprivate\*(Aq); \& #or \& my $public_der = $pk\->export_key_der(\*(Aqpublic\*(Aq); .Ve .PP Since CryptX\-0.36 \f(CW\*(C`export_key_der\*(C'\fR can also export keys in a format that does not explicitly contain curve parameters but only curve \s-1OID.\s0 .PP .Vb 3 \& my $private_der = $pk\->export_key_der(\*(Aqprivate_short\*(Aq); \& #or \& my $public_der = $pk\->export_key_der(\*(Aqpublic_short\*(Aq); .Ve .PP Since CryptX\-0.59 \f(CW\*(C`export_key_der\*(C'\fR can also export keys in \*(L"compressed\*(R" format that defines curve by \s-1OID +\s0 stores public point in compressed form. .PP .Vb 3 \& my $private_pem = $pk\->export_key_der(\*(Aqprivate_compressed\*(Aq); \& #or \& my $public_pem = $pk\->export_key_der(\*(Aqpublic_compressed\*(Aq); .Ve .SS "export_key_pem" .IX Subsection "export_key_pem" .Vb 3 \& my $private_pem = $pk\->export_key_pem(\*(Aqprivate\*(Aq); \& #or \& my $public_pem = $pk\->export_key_pem(\*(Aqpublic\*(Aq); .Ve .PP Since CryptX\-0.36 \f(CW\*(C`export_key_pem\*(C'\fR can also export keys in a format that does not explicitly contain curve parameters but only curve \s-1OID.\s0 .PP .Vb 3 \& my $private_pem = $pk\->export_key_pem(\*(Aqprivate_short\*(Aq); \& #or \& my $public_pem = $pk\->export_key_pem(\*(Aqpublic_short\*(Aq); .Ve .PP Since CryptX\-0.59 \f(CW\*(C`export_key_pem\*(C'\fR can also export keys in \*(L"compressed\*(R" format that defines curve by \s-1OID +\s0 stores public point in compressed form. .PP .Vb 3 \& my $private_pem = $pk\->export_key_pem(\*(Aqprivate_compressed\*(Aq); \& #or \& my $public_pem = $pk\->export_key_pem(\*(Aqpublic_compressed\*(Aq); .Ve .PP Support for password protected \s-1PEM\s0 keys .PP .Vb 3 \& my $private_pem = $pk\->export_key_pem(\*(Aqprivate\*(Aq, $password); \& #or \& my $private_pem = $pk\->export_key_pem(\*(Aqprivate\*(Aq, $password, $cipher); \& \& # supported ciphers: \*(AqDES\-CBC\*(Aq \& # \*(AqDES\-EDE3\-CBC\*(Aq \& # \*(AqSEED\-CBC\*(Aq \& # \*(AqCAMELLIA\-128\-CBC\*(Aq \& # \*(AqCAMELLIA\-192\-CBC\*(Aq \& # \*(AqCAMELLIA\-256\-CBC\*(Aq \& # \*(AqAES\-128\-CBC\*(Aq \& # \*(AqAES\-192\-CBC\*(Aq \& # \*(AqAES\-256\-CBC\*(Aq (DEFAULT) .Ve .SS "export_key_jwk" .IX Subsection "export_key_jwk" \&\fISince: CryptX\-0.022\fR .PP Exports public/private keys as a \s-1JSON\s0 Web Key (\s-1JWK\s0). .PP .Vb 3 \& my $private_json_text = $pk\->export_key_jwk(\*(Aqprivate\*(Aq); \& #or \& my $public_json_text = $pk\->export_key_jwk(\*(Aqpublic\*(Aq); .Ve .PP Also exports public/private keys as a perl \s-1HASH\s0 with \s-1JWK\s0 structure. .PP .Vb 3 \& my $jwk_hash = $pk\->export_key_jwk(\*(Aqprivate\*(Aq, 1); \& #or \& my $jwk_hash = $pk\->export_key_jwk(\*(Aqpublic\*(Aq, 1); .Ve .PP \&\fB\s-1BEWARE:\s0\fR For \s-1JWK\s0 support you need to have \s-1JSON::PP\s0, \s-1JSON::XS\s0 or Cpanel::JSON::XS module. .SS "export_key_jwk_thumbprint" .IX Subsection "export_key_jwk_thumbprint" \&\fISince: CryptX\-0.031\fR .PP Exports the key's \s-1JSON\s0 Web Key Thumbprint as a string. .PP If you don't know what this is, see \s-1RFC 7638\s0 . .PP .Vb 1 \& my $thumbprint = $pk\->export_key_jwk_thumbprint(\*(AqSHA256\*(Aq); .Ve .SS "export_key_raw" .IX Subsection "export_key_raw" Export raw public/private key. Public key is exported in \s-1ASN X9.62\s0 format (compressed or uncompressed), private key is exported as raw bytes (padded with leading zeros to have the same size as the \s-1ECC\s0 curve). .PP .Vb 5 \& my $pubkey_octets = $pk\->export_key_raw(\*(Aqpublic\*(Aq); \& #or \& my $pubckey_octets = $pk\->export_key_raw(\*(Aqpublic_compressed\*(Aq); \& #or \& my $privkey_octets = $pk\->export_key_raw(\*(Aqprivate\*(Aq); .Ve .SS "encrypt" .IX Subsection "encrypt" .Vb 4 \& my $pk = Crypt::PK::ECC\->new($pub_key_filename); \& my $ct = $pk\->encrypt($message); \& #or \& my $ct = $pk\->encrypt($message, $hash_name); \& \& #NOTE: $hash_name can be \*(AqSHA1\*(Aq (DEFAULT), \*(AqSHA256\*(Aq or any other hash supported by Crypt::Digest .Ve .SS "decrypt" .IX Subsection "decrypt" .Vb 2 \& my $pk = Crypt::PK::ECC\->new($priv_key_filename); \& my $pt = $pk\->decrypt($ciphertext); .Ve .SS "sign_message" .IX Subsection "sign_message" .Vb 4 \& my $pk = Crypt::PK::ECC\->new($priv_key_filename); \& my $signature = $priv\->sign_message($message); \& #or \& my $signature = $priv\->sign_message($message, $hash_name); \& \& #NOTE: $hash_name can be \*(AqSHA1\*(Aq (DEFAULT), \*(AqSHA256\*(Aq or any other hash supported by Crypt::Digest .Ve .SS "sign_message_rfc7518" .IX Subsection "sign_message_rfc7518" \&\fISince: CryptX\-0.024\fR .PP Same as sign_message only the signature format is as defined by (\s-1JWA\s0 \- \s-1JSON\s0 Web Algorithms). .PP \&\fB\s-1BEWARE:\s0\fR This creates signatures according to the structure that \s-1RFC 7518\s0 describes but does not apply the \s-1RFC\s0 logic for the hashing algorithm selection. You'll still need to specify, e.g., \s-1SHA256\s0 for a P\-256 key to get a fully RFC\-7518\-compliant signature. .SS "verify_message" .IX Subsection "verify_message" .Vb 4 \& my $pk = Crypt::PK::ECC\->new($pub_key_filename); \& my $valid = $pub\->verify_message($signature, $message) \& #or \& my $valid = $pub\->verify_message($signature, $message, $hash_name); \& \& #NOTE: $hash_name can be \*(AqSHA1\*(Aq (DEFAULT), \*(AqSHA256\*(Aq or any other hash supported by Crypt::Digest .Ve .SS "verify_message_rfc7518" .IX Subsection "verify_message_rfc7518" \&\fISince: CryptX\-0.024\fR .PP Same as verify_message only the signature format is as defined by (\s-1JWA\s0 \- \s-1JSON\s0 Web Algorithms). .PP \&\fB\s-1BEWARE:\s0\fR This verifies signatures according to the structure that \s-1RFC 7518\s0 describes but does not apply the \s-1RFC\s0 logic for the hashing algorithm selection. You'll still need to specify, e.g., \s-1SHA256\s0 for a P\-256 key to get a fully RFC\-7518\-compliant signature. .SS "sign_hash" .IX Subsection "sign_hash" .Vb 2 \& my $pk = Crypt::PK::ECC\->new($priv_key_filename); \& my $signature = $priv\->sign_hash($message_hash); .Ve .SS "sign_hash_rfc7518" .IX Subsection "sign_hash_rfc7518" \&\fISince: CryptX\-0.059\fR .PP Same as sign_hash only the signature format is as defined by (\s-1JWA\s0 \- \s-1JSON\s0 Web Algorithms). .SS "verify_hash" .IX Subsection "verify_hash" .Vb 2 \& my $pk = Crypt::PK::ECC\->new($pub_key_filename); \& my $valid = $pub\->verify_hash($signature, $message_hash); .Ve .SS "verify_hash_rfc7518" .IX Subsection "verify_hash_rfc7518" \&\fISince: CryptX\-0.059\fR .PP Same as verify_hash only the signature format is as defined by (\s-1JWA\s0 \- \s-1JSON\s0 Web Algorithms). .SS "shared_secret" .IX Subsection "shared_secret" .Vb 4 \& # Alice having her priv key $pk and Bob\*(Aqs public key $pkb \& my $pk = Crypt::PK::ECC\->new($priv_key_filename); \& my $pkb = Crypt::PK::ECC\->new($pub_key_filename); \& my $shared_secret = $pk\->shared_secret($pkb); \& \& # Bob having his priv key $pk and Alice\*(Aqs public key $pka \& my $pk = Crypt::PK::ECC\->new($priv_key_filename); \& my $pka = Crypt::PK::ECC\->new($pub_key_filename); \& my $shared_secret = $pk\->shared_secret($pka); # same value as computed by Alice .Ve .SS "is_private" .IX Subsection "is_private" .Vb 4 \& my $rv = $pk\->is_private; \& # 1 .. private key loaded \& # 0 .. public key loaded \& # undef .. no key loaded .Ve .SS "size" .IX Subsection "size" .Vb 2 \& my $size = $pk\->size; \& # returns key size in bytes or undef if no key loaded .Ve .SS "key2hash" .IX Subsection "key2hash" .Vb 1 \& my $hash = $pk\->key2hash; \& \& # returns hash like this (or undef if no key loaded): \& { \& size => 20, # integer: key (curve) size in bytes \& type => 1, # integer: 1 .. private, 0 .. public \& #curve parameters \& curve_A => "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFC", \& curve_B => "1C97BEFC54BD7A8B65ACF89F81D4D4ADC565FA45", \& curve_bits => 160, \& curve_bytes => 20, \& curve_cofactor => 1, \& curve_Gx => "4A96B5688EF573284664698968C38BB913CBFC82", \& curve_Gy => "23A628553168947D59DCC912042351377AC5FB32", \& curve_name => "secp160r1", \& curve_order => "0100000000000000000001F4C8F927AED3CA752257", \& curve_prime => "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFF", \& #private key \& k => "B0EE84A749FE95DF997E33B8F333E12101E824C3", \& #public key point coordinates \& pub_x => "5AE1ACE3ED0AEA9707CE5C0BCE014F6A2F15023A", \& pub_y => "895D57E992D0A15F88D6680B27B701F615FCDC0F", \& } .Ve .SS "curve2hash" .IX Subsection "curve2hash" \&\fISince: CryptX\-0.024\fR .PP .Vb 1 \& my $crv = $pk\->curve2hash; \& \& # returns a hash that can be passed to: $pk\->generate_key($crv) \& { \& A => "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFC", \& B => "1C97BEFC54BD7A8B65ACF89F81D4D4ADC565FA45", \& cofactor => 1, \& Gx => "4A96B5688EF573284664698968C38BB913CBFC82", \& Gy => "23A628553168947D59DCC912042351377AC5FB32", \& order => "0100000000000000000001F4C8F927AED3CA752257", \& prime => "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFF", \& } .Ve .SH "FUNCTIONS" .IX Header "FUNCTIONS" .SS "ecc_encrypt" .IX Subsection "ecc_encrypt" Elliptic Curve Diffie-Hellman (\s-1ECDH\s0) encryption as implemented by libtomcrypt. See method \*(L"encrypt\*(R" below. .PP .Vb 5 \& my $ct = ecc_encrypt($pub_key_filename, $message); \& #or \& my $ct = ecc_encrypt(\e$buffer_containing_pub_key, $message); \& #or \& my $ct = ecc_encrypt($pub_key_filename, $message, $hash_name); \& \& #NOTE: $hash_name can be \*(AqSHA1\*(Aq (DEFAULT), \*(AqSHA256\*(Aq or any other hash supported by Crypt::Digest .Ve .PP \&\s-1ECCDH\s0 Encryption is performed by producing a random key, hashing it, and \s-1XOR\s0'ing the digest against the plaintext. .SS "ecc_decrypt" .IX Subsection "ecc_decrypt" Elliptic Curve Diffie-Hellman (\s-1ECDH\s0) decryption as implemented by libtomcrypt. See method \*(L"decrypt\*(R" below. .PP .Vb 3 \& my $pt = ecc_decrypt($priv_key_filename, $ciphertext); \& #or \& my $pt = ecc_decrypt(\e$buffer_containing_priv_key, $ciphertext); .Ve .SS "ecc_sign_message" .IX Subsection "ecc_sign_message" Elliptic Curve Digital Signature Algorithm (\s-1ECDSA\s0) \- signature generation. See method \*(L"sign_message\*(R" below. .PP .Vb 5 \& my $sig = ecc_sign_message($priv_key_filename, $message); \& #or \& my $sig = ecc_sign_message(\e$buffer_containing_priv_key, $message); \& #or \& my $sig = ecc_sign_message($priv_key, $message, $hash_name); .Ve .SS "ecc_verify_message" .IX Subsection "ecc_verify_message" Elliptic Curve Digital Signature Algorithm (\s-1ECDSA\s0) \- signature verification. See method \*(L"verify_message\*(R" below. .PP .Vb 5 \& ecc_verify_message($pub_key_filename, $signature, $message) or die "ERROR"; \& #or \& ecc_verify_message(\e$buffer_containing_pub_key, $signature, $message) or die "ERROR"; \& #or \& ecc_verify_message($pub_key, $signature, $message, $hash_name) or die "ERROR"; .Ve .SS "ecc_sign_hash" .IX Subsection "ecc_sign_hash" Elliptic Curve Digital Signature Algorithm (\s-1ECDSA\s0) \- signature generation. See method \*(L"sign_hash\*(R" below. .PP .Vb 3 \& my $sig = ecc_sign_hash($priv_key_filename, $message_hash); \& #or \& my $sig = ecc_sign_hash(\e$buffer_containing_priv_key, $message_hash); .Ve .SS "ecc_verify_hash" .IX Subsection "ecc_verify_hash" Elliptic Curve Digital Signature Algorithm (\s-1ECDSA\s0) \- signature verification. See method \*(L"verify_hash\*(R" below. .PP .Vb 3 \& ecc_verify_hash($pub_key_filename, $signature, $message_hash) or die "ERROR"; \& #or \& ecc_verify_hash(\e$buffer_containing_pub_key, $signature, $message_hash) or die "ERROR"; .Ve .SS "ecc_shared_secret" .IX Subsection "ecc_shared_secret" Elliptic curve Diffie-Hellman (\s-1ECDH\s0) \- construct a Diffie-Hellman shared secret with a private and public \s-1ECC\s0 key. See method \*(L"shared_secret\*(R" below. .PP .Vb 2 \& #on Alice side \& my $shared_secret = ecc_shared_secret(\*(AqAlice_priv_ecc1.der\*(Aq, \*(AqBob_pub_ecc1.der\*(Aq); \& \& #on Bob side \& my $shared_secret = ecc_shared_secret(\*(AqBob_priv_ecc1.der\*(Aq, \*(AqAlice_pub_ecc1.der\*(Aq); .Ve .SH "OpenSSL interoperability" .IX Header "OpenSSL interoperability" .Vb 4 \& ### let\*(Aqs have: \& # ECC private key in PEM format \- eckey.priv.pem \& # ECC public key in PEM format \- eckey.pub.pem \& # data file to be signed \- input.data .Ve .SS "Sign by OpenSSL, verify by Crypt::PK::ECC" .IX Subsection "Sign by OpenSSL, verify by Crypt::PK::ECC" Create signature (from commandline): .PP .Vb 1 \& openssl dgst \-sha1 \-sign eckey.priv.pem \-out input.sha1\-ec.sig input.data .Ve .PP Verify signature (Perl code): .PP .Vb 3 \& use Crypt::PK::ECC; \& use Crypt::Digest \*(Aqdigest_file\*(Aq; \& use Crypt::Misc \*(Aqread_rawfile\*(Aq; \& \& my $pkec = Crypt::PK::ECC\->new("eckey.pub.pem"); \& my $signature = read_rawfile("input.sha1\-ec.sig"); \& my $valid = $pkec\->verify_hash($signature, digest_file("SHA1", "input.data"), "SHA1", "v1.5"); \& print $valid ? "SUCCESS" : "FAILURE"; .Ve .SS "Sign by Crypt::PK::ECC, verify by OpenSSL" .IX Subsection "Sign by Crypt::PK::ECC, verify by OpenSSL" Create signature (Perl code): .PP .Vb 3 \& use Crypt::PK::ECC; \& use Crypt::Digest \*(Aqdigest_file\*(Aq; \& use Crypt::Misc \*(Aqwrite_rawfile\*(Aq; \& \& my $pkec = Crypt::PK::ECC\->new("eckey.priv.pem"); \& my $signature = $pkec\->sign_hash(digest_file("SHA1", "input.data"), "SHA1", "v1.5"); \& write_rawfile("input.sha1\-ec.sig", $signature); .Ve .PP Verify signature (from commandline): .PP .Vb 1 \& openssl dgst \-sha1 \-verify eckey.pub.pem \-signature input.sha1\-ec.sig input.data .Ve .SS "Keys generated by Crypt::PK::ECC" .IX Subsection "Keys generated by Crypt::PK::ECC" Generate keys (Perl code): .PP .Vb 2 \& use Crypt::PK::ECC; \& use Crypt::Misc \*(Aqwrite_rawfile\*(Aq; \& \& my $pkec = Crypt::PK::ECC\->new; \& $pkec\->generate_key(\*(Aqsecp160k1\*(Aq); \& write_rawfile("eckey.pub.der", $pkec\->export_key_der(\*(Aqpublic\*(Aq)); \& write_rawfile("eckey.priv.der", $pkec\->export_key_der(\*(Aqprivate\*(Aq)); \& write_rawfile("eckey.pub.pem", $pkec\->export_key_pem(\*(Aqpublic\*(Aq)); \& write_rawfile("eckey.priv.pem", $pkec\->export_key_pem(\*(Aqprivate\*(Aq)); \& write_rawfile("eckey\-passwd.priv.pem", $pkec\->export_key_pem(\*(Aqprivate\*(Aq, \*(Aqsecret\*(Aq)); .Ve .PP Use keys by OpenSSL: .PP .Vb 5 \& openssl ec \-in eckey.priv.der \-text \-inform der \& openssl ec \-in eckey.priv.pem \-text \& openssl ec \-in eckey\-passwd.priv.pem \-text \-inform pem \-passin pass:secret \& openssl ec \-in eckey.pub.der \-pubin \-text \-inform der \& openssl ec \-in eckey.pub.pem \-pubin \-text .Ve .SS "Keys generated by OpenSSL" .IX Subsection "Keys generated by OpenSSL" Generate keys: .PP .Vb 7 \& openssl ecparam \-param_enc explicit \-name prime192v3 \-genkey \-out eckey.priv.pem \& openssl ec \-param_enc explicit \-in eckey.priv.pem \-out eckey.pub.pem \-pubout \& openssl ec \-param_enc explicit \-in eckey.priv.pem \-out eckey.priv.der \-outform der \& openssl ec \-param_enc explicit \-in eckey.priv.pem \-out eckey.pub.der \-outform der \-pubout \& openssl ec \-param_enc explicit \-in eckey.priv.pem \-out eckey.privc.der \-outform der \-conv_form compressed \& openssl ec \-param_enc explicit \-in eckey.priv.pem \-out eckey.pubc.der \-outform der \-pubout \-conv_form compressed \& openssl ec \-param_enc explicit \-in eckey.priv.pem \-passout pass:secret \-des3 \-out eckey\-passwd.priv.pem .Ve .PP Load keys (Perl code): .PP .Vb 1 \& use Crypt::PK::ECC; \& \& my $pkec = Crypt::PK::ECC\->new; \& $pkec\->import_key("eckey.pub.der"); \& $pkec\->import_key("eckey.pubc.der"); \& $pkec\->import_key("eckey.priv.der"); \& $pkec\->import_key("eckey.privc.der"); \& $pkec\->import_key("eckey.pub.pem"); \& $pkec\->import_key("eckey.priv.pem"); \& $pkec\->import_key("eckey\-passwd.priv.pem", "secret"); .Ve .SH "SEE ALSO" .IX Header "SEE ALSO" .IP "\(bu" 4 .IP "\(bu" 4 .IP "\(bu" 4