@@ -131,6 +131,114 @@ def __eq__(self, other):
131131 def __ne__ (self , other ):
132132 return not (self == other )
133133
134+ @classmethod
135+ def load_pkcs1_der (cls , keyfile ):
136+ r'''Loads a key in PKCS#1 DER format.
137+
138+ @param keyfile: contents of a DER-encoded file that contains the private
139+ key.
140+ @return: a PrivateKey object
141+
142+ First let's construct a DER encoded key:
143+
144+ >>> import base64
145+ >>> b64der = 'MC4CAQACBQDeKYlRAgMBAAECBQDHn4npAgMA/icCAwDfxwIDANcXAgInbwIDAMZt'
146+ >>> der = base64.decodestring(b64der)
147+
148+ This loads the file:
149+
150+ >>> PrivateKey.load_pkcs1_der(der)
151+ PrivateKey(3727264081, 65537, 3349121513, 65063, 57287)
152+
153+ '''
154+
155+ from pyasn1 .codec .der import decoder
156+ (priv , _ ) = decoder .decode (keyfile )
157+
158+ # ASN.1 contents of DER encoded private key:
159+ #
160+ # RSAPrivateKey ::= SEQUENCE {
161+ # version Version,
162+ # modulus INTEGER, -- n
163+ # publicExponent INTEGER, -- e
164+ # privateExponent INTEGER, -- d
165+ # prime1 INTEGER, -- p
166+ # prime2 INTEGER, -- q
167+ # exponent1 INTEGER, -- d mod (p-1)
168+ # exponent2 INTEGER, -- d mod (q-1)
169+ # coefficient INTEGER, -- (inverse of q) mod p
170+ # otherPrimeInfos OtherPrimeInfos OPTIONAL
171+ # }
172+
173+ if priv [0 ] != 0 :
174+ raise ValueError ('Unable to read this file, version %s != 0' % priv [0 ])
175+
176+ return cls (* priv [1 :9 ])
177+
178+ def save_pkcs1_der (self ):
179+ '''Saves the private key in PKCS#1 DER format.
180+
181+ @param priv_key: the private key to save
182+ @returns: the DER-encoded private key.
183+ '''
184+
185+ from pyasn1 .type import univ , namedtype , tag
186+ from pyasn1 .codec .der import encoder
187+
188+ class AsnPrivKey (univ .Sequence ):
189+ componentType = namedtype .NamedTypes (
190+ namedtype .NamedType ('version' , univ .Integer ()),
191+ namedtype .NamedType ('modulus' , univ .Integer ()),
192+ namedtype .NamedType ('publicExponent' , univ .Integer ()),
193+ namedtype .NamedType ('privateExponent' , univ .Integer ()),
194+ namedtype .NamedType ('prime1' , univ .Integer ()),
195+ namedtype .NamedType ('prime2' , univ .Integer ()),
196+ namedtype .NamedType ('exponent1' , univ .Integer ()),
197+ namedtype .NamedType ('exponent2' , univ .Integer ()),
198+ namedtype .NamedType ('coefficient' , univ .Integer ()),
199+ )
200+
201+ # Create the ASN object
202+ asn_key = AsnPrivKey ()
203+ asn_key .setComponentByName ('version' , 0 )
204+ asn_key .setComponentByName ('modulus' , self .n )
205+ asn_key .setComponentByName ('publicExponent' , self .e )
206+ asn_key .setComponentByName ('privateExponent' , self .d )
207+ asn_key .setComponentByName ('prime1' , self .p )
208+ asn_key .setComponentByName ('prime2' , self .q )
209+ asn_key .setComponentByName ('exponent1' , self .exp1 )
210+ asn_key .setComponentByName ('exponent2' , self .exp2 )
211+ asn_key .setComponentByName ('coefficient' , self .coef )
212+
213+ return encoder .encode (asn_key )
214+
215+ @classmethod
216+ def load_pkcs1_pem (cls , keyfile ):
217+ '''Loads a PKCS#1 PEM-encoded private key file.
218+
219+ The contents of the file before the "-----BEGIN RSA PRIVATE KEY-----" and
220+ after the "-----END RSA PRIVATE KEY-----" lines is ignored.
221+
222+ @param keyfile: contents of a PEM-encoded file that contains the private
223+ key.
224+ @return: a PrivateKey object
225+ '''
226+
227+ der = rsa .pem .load_pem (keyfile , 'RSA PRIVATE KEY' )
228+ return cls .load_pkcs1_der (der )
229+
230+ def save_pkcs1_pem (self ):
231+ '''Saves a PKCS#1 PEM-encoded private key file.
232+
233+ @param keyfile: a PrivateKey object
234+ @return: contents of a PEM-encoded file that contains the private key.
235+ '''
236+
237+ der = self .save_pkcs1_der ()
238+ return rsa .pem .save_pem (der , 'RSA PRIVATE KEY' )
239+
240+
241+
134242def extended_gcd (a , b ):
135243 """Returns a tuple (r, i, j) such that r = gcd(a, b) = ia + jb
136244 """
@@ -245,112 +353,8 @@ def newkeys(nbits):
245353 PrivateKey (n , e , d , p , q )
246354 )
247355
248- def load_private_key_der (keyfile ):
249- r'''Loads a key in DER format.
250-
251- @param keyfile: contents of a DER-encoded file that contains the private
252- key.
253- @return: a PrivateKey object
254-
255- First let's construct a DER encoded key:
256-
257- >>> import base64
258- >>> b64der = 'MC4CAQACBQDeKYlRAgMBAAECBQDHn4npAgMA/icCAwDfxwIDANcXAgInbwIDAMZt'
259- >>> der = base64.decodestring(b64der)
260-
261- This loads the file:
262-
263- >>> load_private_key_der(der)
264- PrivateKey(3727264081, 65537, 3349121513, 65063, 57287)
265-
266- '''
267-
268- from pyasn1 .codec .der import decoder
269- (priv , _ ) = decoder .decode (keyfile )
270-
271- # ASN.1 contents of DER encoded private key:
272- #
273- # RSAPrivateKey ::= SEQUENCE {
274- # version Version,
275- # modulus INTEGER, -- n
276- # publicExponent INTEGER, -- e
277- # privateExponent INTEGER, -- d
278- # prime1 INTEGER, -- p
279- # prime2 INTEGER, -- q
280- # exponent1 INTEGER, -- d mod (p-1)
281- # exponent2 INTEGER, -- d mod (q-1)
282- # coefficient INTEGER, -- (inverse of q) mod p
283- # otherPrimeInfos OtherPrimeInfos OPTIONAL
284- # }
285-
286- if priv [0 ] != 0 :
287- raise ValueError ('Unable to read this file, version %s != 0' % priv [0 ])
288-
289- return PrivateKey (* priv [1 :9 ])
290-
291- def save_private_key_der (priv_key ):
292- '''Saves the private key in DER format.
293-
294- @param priv_key: the private key to save
295- @returns: the DER-encoded private key.
296- '''
297-
298- from pyasn1 .type import univ , namedtype , tag
299- from pyasn1 .codec .der import encoder
300-
301- class AsnPrivKey (univ .Sequence ):
302- componentType = namedtype .NamedTypes (
303- namedtype .NamedType ('version' , univ .Integer ()),
304- namedtype .NamedType ('modulus' , univ .Integer ()),
305- namedtype .NamedType ('publicExponent' , univ .Integer ()),
306- namedtype .NamedType ('privateExponent' , univ .Integer ()),
307- namedtype .NamedType ('prime1' , univ .Integer ()),
308- namedtype .NamedType ('prime2' , univ .Integer ()),
309- namedtype .NamedType ('exponent1' , univ .Integer ()),
310- namedtype .NamedType ('exponent2' , univ .Integer ()),
311- namedtype .NamedType ('coefficient' , univ .Integer ()),
312- )
313-
314- # Create the ASN object
315- asn_key = AsnPrivKey ()
316- asn_key .setComponentByName ('version' , 0 )
317- asn_key .setComponentByName ('modulus' , priv_key .n )
318- asn_key .setComponentByName ('publicExponent' , priv_key .e )
319- asn_key .setComponentByName ('privateExponent' , priv_key .d )
320- asn_key .setComponentByName ('prime1' , priv_key .p )
321- asn_key .setComponentByName ('prime2' , priv_key .q )
322- asn_key .setComponentByName ('exponent1' , priv_key .exp1 )
323- asn_key .setComponentByName ('exponent2' , priv_key .exp2 )
324- asn_key .setComponentByName ('coefficient' , priv_key .coef )
325-
326- return encoder .encode (asn_key )
327-
328- def load_private_key_pem (keyfile ):
329- '''Loads a PEM-encoded private key file.
330-
331- The contents of the file before the "-----BEGIN RSA PRIVATE KEY-----" and
332- after the "-----END RSA PRIVATE KEY-----" lines is ignored.
333-
334- @param keyfile: contents of a PEM-encoded file that contains the private
335- key.
336- @return: a PrivateKey object
337- '''
338-
339- der = rsa .pem .load_pem (keyfile , 'RSA PRIVATE KEY' )
340- return load_private_key_der (der )
341-
342- def save_private_key_pem (priv_key ):
343- '''Saves a PEM-encoded private key file.
344-
345- @param keyfile: a PrivateKey object
346- @return: contents of a PEM-encoded file that contains the private key.
347- '''
348-
349- der = save_private_key_der (priv_key )
350- return rsa .pem .save_pem (der , 'RSA PRIVATE KEY' )
351-
352-
353- __all__ = ['PublicKey' , 'PrivateKey' , 'newkeys' , 'load' ]
356+ __all__ = ['PublicKey' , 'PrivateKey' , 'newkeys' , 'load_private_key_der' ,
357+ 'load_private_key_pem' , 'save_private_key_der' , 'save_private_key_pem' ]
354358
355359if __name__ == '__main__' :
356360 import doctest
0 commit comments