@@ -25,7 +25,7 @@ def jwk_from_file(filename: str, private: bool = True) -> JWK:
2525 return key_from_jwk_dict (jwk_dict , private = private )
2626
2727
28- def pem2rsa (filename : str , kid : str = None , private : bool = False , passphrase : str = None ) -> JWK :
28+ def pem2rsa (filename : str , kid : Optional [ str ] = None , private : bool = False , passphrase : Optional [ str ] = None ) -> JWK :
2929 """Convert RSA key from PEM to JWK"""
3030 if private :
3131 key = import_private_rsa_key_from_file (filename , passphrase )
@@ -36,7 +36,7 @@ def pem2rsa(filename: str, kid: str = None, private: bool = False, passphrase: s
3636 return jwk
3737
3838
39- def pem2ec (filename : str , kid : str = None , private : bool = False , passphrase : str = None ) -> JWK :
39+ def pem2ec (filename : str , kid : Optional [ str ] = None , private : bool = False , passphrase : Optional [ str ] = None ) -> JWK :
4040 """Convert EC key from PEM to JWK"""
4141 if private :
4242 key = import_private_key_from_file (filename , passphrase )
@@ -54,20 +54,35 @@ def bin2jwk(filename: str, kid: str) -> bytes:
5454 return SYMKey (kid = kid , key = content )
5555
5656
57- def pem2jwk (filename : str , kid : str , private : bool = False ) -> JWK :
57+ def pem2jwk (filename : str , kid : Optional [ str ] = None , kty : Optional [ str ] = None , private : bool = False , passphrase : Optional [ str ] = None ) -> JWK :
5858 """Read PEM from filename and return JWK"""
5959 with open (filename , 'rt' ) as file :
6060 content = file .readlines ()
6161 header = content [0 ]
6262
6363 if private :
64- passphrase = getpass ('Private key passphrase: ' )
64+ if passphrase is None :
65+ passphrase = getpass ('Private key passphrase: ' )
6566 if len (passphrase ) == 0 :
6667 passphrase = None
6768 else :
6869 passphrase = None
6970
70- if 'BEGIN EC PRIVATE KEY' in header :
71+ if 'BEGIN PUBLIC KEY' in header :
72+ if kty is not None and kty == 'EC' :
73+ jwk = pem2ec (filename , kid , private = False )
74+ elif kty is not None and kty == 'RSA' :
75+ jwk = pem2rsa (filename , kid , private = False )
76+ else :
77+ raise ValueError ("Unknown key type" )
78+ elif 'BEGIN PRIVATE KEY' in header :
79+ if kty is not None and kty == 'EC' :
80+ jwk = pem2ec (filename , kid , private = True , passphrase = passphrase )
81+ elif kty is not None and kty == 'RSA' :
82+ jwk = pem2rsa (filename , kid , private = True , passphrase = passphrase )
83+ else :
84+ raise ValueError ("Unknown key type" )
85+ elif 'BEGIN EC PRIVATE KEY' in header :
7186 jwk = pem2ec (filename , kid , private = True , passphrase = passphrase )
7287 elif 'BEGIN EC PUBLIC KEY' in header :
7388 jwk = pem2ec (filename , kid , private = False )
@@ -81,18 +96,22 @@ def pem2jwk(filename: str, kid: str, private: bool = False) -> JWK:
8196 return jwk
8297
8398
84- def export_jwk (jwk : JWK , private : bool = False ) -> bytes :
99+ def export_jwk (jwk : JWK , private : bool = False , encrypt : bool = False , passphrase : Optional [ str ] = None ) -> bytes :
85100 """Export JWK as PEM/bin"""
86101
87102 if jwk .kty == 'oct' :
88103 return jwk .key
89104
90105 if private :
91- passphrase = getpass ('Private key passphrase: ' )
106+ if encrypt :
107+ if passphrase is None :
108+ passphrase = getpass ('Private key passphrase: ' )
109+ else :
110+ passphrase = None
92111 if passphrase :
93112 enc = serialization .BestAvailableEncryption (passphrase .encode ())
94113 else :
95- enc = serialization .NoEncryption
114+ enc = serialization .NoEncryption ()
96115 serialized = jwk .priv_key .private_bytes (
97116 encoding = serialization .Encoding .PEM ,
98117 format = serialization .PrivateFormat .PKCS8 ,
@@ -134,10 +153,18 @@ def main():
134153 dest = 'kid' ,
135154 metavar = 'key_id' ,
136155 help = 'Key ID' )
156+ parser .add_argument ('--kty' ,
157+ dest = 'kty' ,
158+ metavar = 'type' ,
159+ help = 'Key type' )
137160 parser .add_argument ('--private' ,
138161 dest = 'private' ,
139162 action = 'store_true' ,
140163 help = "Output private key" )
164+ parser .add_argument ('--encrypt' ,
165+ dest = 'encrypt' ,
166+ action = 'store_true' ,
167+ help = "Encrypt private key" )
141168 parser .add_argument ('--output' ,
142169 dest = 'output' ,
143170 metavar = 'filename' ,
@@ -149,13 +176,13 @@ def main():
149176
150177 if f .endswith ('.json' ):
151178 jwk = jwk_from_file (f , args .private )
152- serialized = export_jwk (jwk , args .private )
179+ serialized = export_jwk (jwk , private = args .private , encrypt = args . encrypt )
153180 output_bytes (data = serialized , binary = (jwk .kty == 'oct' ), filename = args .output )
154181 elif f .endswith ('.bin' ):
155- jwk = bin2jwk (f , args .kid )
182+ jwk = bin2jwk (filename = f , kid = args .kid )
156183 output_jwk (jwk = jwk , private = True , filename = args .output )
157184 elif f .endswith ('.pem' ):
158- jwk = pem2jwk (f , args .kid , args .private )
185+ jwk = pem2jwk (filename = f , kid = args .kid , private = args .private , kty = args . kty )
159186 output_jwk (jwk = jwk , private = args .private , filename = args .output )
160187 else :
161188 exit (- 1 )
0 commit comments