Crypt::PK::ECC+RSA export_key_jwk() allows to export a perl HASH with JWK structure
Karel Miko
8 years ago
439 | 439 | } |
440 | 440 | |
441 | 441 | sub export_key_jwk { |
442 | my ($self, $type) = @_; | |
442 | my ($self, $type, $wanthash) = @_; | |
443 | 443 | my $kh = $self->key2hash; |
444 | 444 | my $curve = $self->_curve_name_lookup($kh); |
445 | 445 | $curve = 'P-192' if $curve =~ /(secp192r1|nistp192|prime192v1)/; |
453 | 453 | $kh->{$_} = "0$kh->{$_}" if length($kh->{$_}) % 2; |
454 | 454 | } |
455 | 455 | # NOTE: x + y are not necessary in privkey |
456 | # but they are used in https://tools.ietf.org/html/draft-ietf-jose-json-web-key-41#appendix-A.2 | |
457 | return sprintf '{"kty":"EC","crv":"%s","x":"%s","y":"%s","d":"%s"}', | |
458 | $curve, | |
459 | encode_base64url(pack("H*", $kh->{pub_x})), | |
460 | encode_base64url(pack("H*", $kh->{pub_y})), | |
461 | encode_base64url(pack("H*", $kh->{k})); | |
456 | # but they are used in https://tools.ietf.org/html/rfc7517#appendix-A.2 | |
457 | my $hash = { | |
458 | kty => "EC", crv=>$curve, | |
459 | x => encode_base64url(pack("H*", $kh->{pub_x})), | |
460 | y => encode_base64url(pack("H*", $kh->{pub_y})), | |
461 | d => encode_base64url(pack("H*", $kh->{k})), | |
462 | }; | |
463 | return $wanthash ? $hash : encode_json($hash); | |
462 | 464 | } |
463 | 465 | elsif ($type && $type eq 'public') { |
464 | 466 | return unless $kh->{pub_x} && $kh->{pub_y}; |
465 | 467 | for (qw/pub_x pub_y/) { |
466 | 468 | $kh->{$_} = "0$kh->{$_}" if length($kh->{$_}) % 2; |
467 | 469 | } |
468 | return sprintf '{"kty":"EC","crv":"%s","x":"%s","y":"%s"}', | |
469 | $curve, | |
470 | encode_base64url(pack("H*", $kh->{pub_x})), | |
471 | encode_base64url(pack("H*", $kh->{pub_y})); | |
470 | my $hash = { | |
471 | kty => "EC", crv=>$curve, | |
472 | x => encode_base64url(pack("H*", $kh->{pub_x})), | |
473 | y => encode_base64url(pack("H*", $kh->{pub_y})), | |
474 | }; | |
475 | return $wanthash ? $hash : encode_json($hash); | |
472 | 476 | } |
473 | 477 | } |
474 | 478 | |
494 | 498 | return $self->_import_hex($key->{x}, $key->{y}, $key->{d}, $curve); |
495 | 499 | } |
496 | 500 | } |
497 | croak "FATAL: unexpected key hash"; | |
501 | croak "FATAL: unexpected ECC key hash"; | |
498 | 502 | } |
499 | 503 | |
500 | 504 | my $data; |
863 | 867 | |
864 | 868 | Supported key formats: |
865 | 869 | |
870 | # all formats can be loaded from a file | |
871 | my $pk = Crypt::PK::ECC->new($filename); | |
872 | ||
873 | # or from a buffer containing the key | |
874 | my $pk = Crypt::PK::ECC->new(\$buffer_with_key); | |
875 | ||
866 | 876 | =over |
867 | 877 | |
868 | 878 | =item * EC private keys with with all curve parameters |
1025 | 1035 | |
1026 | 1036 | =head2 export_key_jwk |
1027 | 1037 | |
1028 | Exports public/private keys as a JSON Web Key. | |
1038 | Exports public/private keys as a JSON Web Key (JWK). | |
1029 | 1039 | |
1030 | 1040 | my $private_json_text = $pk->export_key_jwk('private'); |
1031 | 1041 | #or |
1032 | 1042 | my $public_json_text = $pk->export_key_jwk('public'); |
1043 | ||
1044 | Also exports public/private keys as a perl HASH with JWK structure. | |
1045 | ||
1046 | my $jwk_hash = $pk->export_key_jwk('private', 1); | |
1047 | #or | |
1048 | my $jwk_hash = $pk->export_key_jwk('public', 1); | |
1033 | 1049 | |
1034 | 1050 | =head2 export_key_raw |
1035 | 1051 |
38 | 38 | } |
39 | 39 | |
40 | 40 | sub export_key_jwk { |
41 | my ($self, $type) = @_; | |
41 | my ($self, $type, $wanthash) = @_; | |
42 | 42 | my $kh = $self->key2hash; |
43 | 43 | if ($type eq 'private') { |
44 | 44 | return unless $kh->{N} && $kh->{e} && $kh->{d} && $kh->{p} && $kh->{q} && $kh->{dP} && $kh->{dQ} && $kh->{qP}; |
45 | 45 | for (qw/N e d p q dP dQ qP/) { |
46 | 46 | $kh->{$_} = "0$kh->{$_}" if length($kh->{$_}) % 2; |
47 | 47 | } |
48 | return sprintf '{"kty":"RSA","n":"%s","e":"%s","d":"%s","p":"%s","q":"%s","dp":"%s","dq":"%s","qi":"%s"}', | |
49 | encode_base64url(pack("H*", $kh->{N})), | |
50 | encode_base64url(pack("H*", $kh->{e})), | |
51 | encode_base64url(pack("H*", $kh->{d})), | |
52 | encode_base64url(pack("H*", $kh->{p})), | |
53 | encode_base64url(pack("H*", $kh->{q})), | |
54 | encode_base64url(pack("H*", $kh->{dP})), | |
55 | encode_base64url(pack("H*", $kh->{dQ})), | |
56 | encode_base64url(pack("H*", $kh->{qP})); | |
48 | my $hash = { | |
49 | kty => "RSA", | |
50 | n => encode_base64url(pack("H*", $kh->{N})), | |
51 | e => encode_base64url(pack("H*", $kh->{e})), | |
52 | d => encode_base64url(pack("H*", $kh->{d})), | |
53 | p => encode_base64url(pack("H*", $kh->{p})), | |
54 | q => encode_base64url(pack("H*", $kh->{q})), | |
55 | dp => encode_base64url(pack("H*", $kh->{dP})), | |
56 | dq => encode_base64url(pack("H*", $kh->{dQ})), | |
57 | qi => encode_base64url(pack("H*", $kh->{qP})), | |
58 | }; | |
59 | return $wanthash ? $hash : encode_json($hash); | |
57 | 60 | } |
58 | 61 | elsif ($type eq 'public') { |
59 | 62 | return unless $kh->{N} && $kh->{e}; |
60 | 63 | for (qw/N e/) { |
61 | 64 | $kh->{$_} = "0$kh->{$_}" if length($kh->{$_}) % 2; |
62 | 65 | } |
63 | return sprintf '{"kty":"RSA","n":"%s","e":"%s"}', | |
64 | encode_base64url(pack("H*", $kh->{N})), | |
65 | encode_base64url(pack("H*", $kh->{e})); | |
66 | my $hash = { | |
67 | kty => "RSA", | |
68 | n => encode_base64url(pack("H*", $kh->{N})), | |
69 | e => encode_base64url(pack("H*", $kh->{e})), | |
70 | }; | |
71 | return $wanthash ? $hash : encode_json($hash); | |
66 | 72 | } |
67 | 73 | } |
68 | 74 | |
83 | 89 | } |
84 | 90 | return $self->_import_hex($key->{n}, $key->{e}, $key->{d}, $key->{p}, $key->{q}, $key->{dp}, $key->{dq}, $key->{qi}); |
85 | 91 | } |
92 | croak "FATAL: unexpected RSA key hash"; | |
86 | 93 | } |
87 | 94 | |
88 | 95 | my $data; |
365 | 372 | }); |
366 | 373 | |
367 | 374 | Supported key formats: |
375 | ||
376 | # all formats can be loaded from a file | |
377 | my $pk = Crypt::PK::RSA->new($filename); | |
378 | ||
379 | # or from a buffer containing the key | |
380 | my $pk = Crypt::PK::RSA->new(\$buffer_with_key); | |
368 | 381 | |
369 | 382 | =over |
370 | 383 | |
536 | 549 | |
537 | 550 | =head2 export_key_jwk |
538 | 551 | |
539 | Exports public/private keys as a JSON Web Key. | |
552 | Exports public/private keys as a JSON Web Key (JWK). | |
540 | 553 | |
541 | 554 | my $private_json_text = $pk->export_key_jwk('private'); |
542 | 555 | #or |
543 | 556 | my $public_json_text = $pk->export_key_jwk('public'); |
557 | ||
558 | Also exports public/private keys as a perl HASH with JWK structure. | |
559 | ||
560 | my $jwk_hash = $pk->export_key_jwk('private', 1); | |
561 | #or | |
562 | my $jwk_hash = $pk->export_key_jwk('public', 1); | |
544 | 563 | |
545 | 564 | =head2 encrypt |
546 | 565 |
2 | 2 | use strict; |
3 | 3 | use warnings ; |
4 | 4 | |
5 | our $VERSION = '0.024'; | |
5 | our $VERSION = '0.025'; | |
6 | 6 | |
7 | 7 | require XSLoader; |
8 | 8 | XSLoader::load('CryptX', $VERSION); |
58 | 58 | ok($rsa->is_private, "RSA private test HASH1"); |
59 | 59 | my $jwk = $rsa->export_key_jwk('private'); |
60 | 60 | my $jwkp = $rsa->export_key_jwk('public'); |
61 | my $jwkh = $rsa->export_key_jwk('private', 1); | |
62 | my $jwkhp = $rsa->export_key_jwk('public', 1); | |
63 | is($jwkh->{kty}, "RSA", "RSA kty test export_key_jwk as hash"); | |
64 | is($jwkhp->{kty}, "RSA", "RSA(pub) kty test export_key_jwk as hash"); | |
65 | ok(exists $jwkhp->{n}, "RSA(pub) n test export_key_jwk as hash"); | |
66 | ok(exists $jwkhp->{e}, "RSA(pub) e test export_key_jwk as hash"); | |
67 | ok(!exists $jwkhp->{p}, "RSA(pub) p test export_key_jwk as hash"); | |
68 | ok(exists $jwkh->{n}, "RSA n test export_key_jwk as hash"); | |
69 | ok(exists $jwkh->{e}, "RSA e test export_key_jwk as hash"); | |
70 | ok(exists $jwkh->{p}, "RSA p test export_key_jwk as hash"); | |
61 | 71 | ### jwk re-import private key |
62 | 72 | $rsa->import_key(\$jwk); |
63 | 73 | $kh = $rsa->key2hash; |
153 | 163 | ok($ec->is_private, "EC private test HASH1"); |
154 | 164 | my $jwk = $ec->export_key_jwk('private'); |
155 | 165 | my $jwkp = $ec->export_key_jwk('public'); |
166 | my $jwkh = $ec->export_key_jwk('private', 1); | |
167 | my $jwkhp = $ec->export_key_jwk('public', 1); | |
168 | is($jwkh->{kty}, "EC", "ECC kty test export_key_jwk as hash"); | |
169 | is($jwkhp->{kty}, "EC", "ECC(pub) kty test export_key_jwk as hash"); | |
170 | ok(exists $jwkhp->{x}, "ECC(pub) x test export_key_jwk as hash"); | |
171 | ok(exists $jwkhp->{y}, "ECC(pub) y test export_key_jwk as hash"); | |
172 | ok(!exists $jwkhp->{d}, "ECC(pub) d test export_key_jwk as hash"); | |
173 | ok(exists $jwkh->{x}, "ECC x test export_key_jwk as hash"); | |
174 | ok(exists $jwkh->{y}, "ECC y test export_key_jwk as hash"); | |
175 | ok(exists $jwkh->{d}, "ECC d test export_key_jwk as hash"); | |
156 | 176 | ### jwk re-import private key |
157 | 177 | $ec->import_key(\$jwk); |
158 | 178 | $kh = $ec->key2hash; |