pycryptodome/lib/Crypto/PublicKey/RSA.py

713 lines
28 KiB
Python
Raw Normal View History

# -*- coding: utf-8 -*-
#
# PublicKey/RSA.py : RSA public key primitive
#
# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net>
#
# ===================================================================
# The contents of this file are dedicated to the public domain. To
# the extent that dedication to the public domain is not available,
# everyone is granted a worldwide, perpetual, royalty-free,
# non-exclusive license to exercise all rights associated with the
# contents of this file for any purpose whatsoever.
# No rights are reserved.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
# ===================================================================
"""RSA public-key cryptography algorithm (signature and encryption).
RSA_ is the most widespread and used public key algorithm. Its security is
based on the difficulty of factoring large integers. The algorithm has
withstood attacks for 30 years, and it is therefore considered reasonably
secure for new designs.
The algorithm can be used for both confidentiality (encryption) and
authentication (digital signature). It is worth noting that signing and
decryption are significantly slower than verification and encryption.
The cryptograhic strength is primarily linked to the length of the modulus *n*.
In 2012, a sufficient length is deemed to be 2048 bits. For more information,
see the most recent ECRYPT_ report.
Both RSA ciphertext and RSA signature are as big as the modulus *n* (256
bytes if *n* is 2048 bit long).
This module provides facilities for generating fresh, new RSA keys, constructing
them from known components, exporting them, and importing them.
>>> from Crypto.PublicKey import RSA
>>>
>>> key = RSA.generate(2048)
>>> f = open('mykey.pem','w')
>>> f.write(key.exportKey('PEM'))
>>> f.close()
...
>>> f = open('mykey.pem','r')
>>> key = RSA.importKey(f.read())
Even though you may choose to directly use the methods of an RSA key object
to perform the primitive cryptographic operations (e.g. `_RSAobj._encrypt`),
it is recommended to use one of the standardized schemes instead (like
`Crypto.Cipher.PKCS1_v1_5` or `Crypto.Signature.PKCS1_v1_5`).
.. _RSA: http://en.wikipedia.org/wiki/RSA_%28algorithm%29
.. _ECRYPT: http://www.ecrypt.eu.org/documents/D.SPA.17.pdf
:sort: generate,construct,importKey
"""
__all__ = ['generate', 'construct', 'importKey', 'RSAImplementation',
'_RSAobj', 'oid' , 'algorithmIdentifier' ]
from Crypto.Util.py3compat import *
import binascii
import struct
2014-06-11 15:46:22 +02:00
from Crypto import Random
from Crypto.IO import PKCS8, PEM
from Crypto.Util.asn1 import (
DerNull,
DerSequence,
DerBitString,
DerObjectId,
newDerSequence,
newDerBitString
)
2014-12-05 08:12:51 -05:00
from Crypto.Math.Numbers import Integer
from Crypto.Math.Primality import (test_probable_prime,
generate_probable_prime, COMPOSITE)
def _decode_der(obj_class, binstr):
"""Instantiate a DER object class, decode a DER binary string in it, and
return the object."""
der = obj_class()
der.decode(binstr)
return der
class _RSAobj(object):
"""Class defining an actual RSA key.
:undocumented: __getstate__, __setstate__, __repr__, __getattr__
"""
#: Dictionary of RSA parameters.
#:
#: A public key will only have the following entries:
#:
#: - **n**, the modulus.
#: - **e**, the public exponent.
#:
#: A private key will also have:
#:
#: - **d**, the private exponent.
#: - **p**, the first factor of n.
#: - **q**, the second factor of n.
#: - **u**, the CRT coefficient (1/p) mod q.
_keydata = ['n', 'e', 'd', 'p', 'q', 'u']
2014-12-05 08:12:51 -05:00
def __init__(self, key_dict, randfunc):
input_set = set(key_dict.keys())
public_set = set(('n' , 'e'))
private_set = public_set | set(('p' , 'q', 'd', 'u'))
if input_set not in (private_set, public_set):
raise ValueError("Some RSA components are missing")
self._key = dict(key_dict)
self._randfunc = randfunc
def __getattr__(self, attrname):
2014-12-05 08:12:51 -05:00
try:
return int(self._key[attrname])
except KeyError:
raise AttributeError(attrname)
def _encrypt(self, plaintext):
if not 0 < plaintext < self.n:
raise ValueError("Plaintext too large")
2014-12-05 08:12:51 -05:00
e, n = self._key['e'], self._key['n']
return int(pow(Integer(plaintext), e, n))
def _decrypt(self, ciphertext):
if not 0 < ciphertext < self.n:
raise ValueError("Ciphertext too large")
2014-12-05 08:12:51 -05:00
if not self.has_private():
raise TypeError("This is not a private key")
e, d, n, p, q, u = [self._key[comp] for comp in 'e', 'd', 'n', 'p', 'q', 'u']
# Blinded RSA decryption (to prevent timing attacks):
# Step 1: Generate random secret blinding factor r, such that 0 < r < n-1
2014-12-05 08:12:51 -05:00
r = Integer.random_range(min_inclusive=1, max_exclusive=n, randfunc=self._randfunc)
# Step 2: Compute c' = c * r**e mod n
2014-12-05 08:12:51 -05:00
cp = Integer(ciphertext) * pow(r, e, n) % n
# Step 3: Compute m' = c'**d mod n (ordinary RSA decryption)
2014-12-05 08:12:51 -05:00
m1 = pow(cp, d % (p - 1), p)
m2 = pow(cp, d % (q - 1), q)
h = m2 - m1
while h < 0:
h += q
h = (h * u) % q
mp = h * p + m1
# Step 4: Compute m = m**(r-1) mod n
2014-12-05 08:12:51 -05:00
return (r.inverse(n) * mp) % n
def has_private(self):
2014-12-05 08:12:51 -05:00
return 'd' in self._key
def size(self):
2014-12-05 08:12:51 -05:00
return self._key['p'].size_in_bits() - 1
def publickey(self):
2014-12-05 08:12:51 -05:00
return _RSAobj(dict([(k, self._key[k]) for k in 'n', 'e']), self._randfunc)
def __eq__(self, other):
2014-12-05 08:12:51 -05:00
return self._key == other._key
def __ne__(self, other):
2014-12-05 08:12:51 -05:00
return self._key != other._key
def __getstate__(self):
# RSA key is not pickable
from pickle import PicklingError
raise PicklingError
def __repr__(self):
attrs = []
for k in self._keydata:
if k == 'n':
attrs.append("n(%d)" % (self.size()+1,))
elif hasattr(self.key, k):
attrs.append(k)
if self.has_private():
attrs.append("private")
# PY3K: This is meant to be text, do not change to bytes (data)
return "<%s @0x%x %s>" % (self.__class__.__name__, id(self), ",".join(attrs))
def exportKey(self, format='PEM', passphrase=None, pkcs=1, protection=None):
"""Export this RSA key.
:Parameters:
format : string
The format to use for wrapping the key:
- *'DER'*. Binary encoding.
- *'PEM'*. Textual encoding, done according to `RFC1421`_/`RFC1423`_.
- *'OpenSSH'*. Textual encoding, done according to OpenSSH specification.
Only suitable for public keys (not private keys).
passphrase : string
For private keys only. The pass phrase used for deriving the encryption
key.
pkcs : integer
For *DER* and *PEM* format only.
The PKCS standard to follow for assembling the components of the key.
You have two choices:
- **1** (default): the public key is embedded into
an X.509 ``SubjectPublicKeyInfo`` DER SEQUENCE.
The private key is embedded into a `PKCS#1`_
``RSAPrivateKey`` DER SEQUENCE.
- **8**: the private key is embedded into a `PKCS#8`_
``PrivateKeyInfo`` DER SEQUENCE. This value cannot be used
for public keys.
protection : string
The encryption scheme to use for protecting the private key.
If ``None`` (default), the behavior depends on ``format``:
- For *DER*, the *PBKDF2WithHMAC-SHA1AndDES-EDE3-CBC*
scheme is used. The following operations are performed:
1. A 16 byte Triple DES key is derived from the passphrase
using `Crypto.Protocol.KDF.PBKDF2` with 8 bytes salt,
and 1 000 iterations of `Crypto.Hash.HMAC`.
2. The private key is encrypted using CBC.
3. The encrypted key is encoded according to PKCS#8.
- For *PEM*, the obsolete PEM encryption scheme is used.
It is based on MD5 for key derivation, and Triple DES for encryption.
Specifying a value for ``protection`` is only meaningful for PKCS#8
(that is, ``pkcs=8``) and only if a pass phrase is present too.
The supported schemes for PKCS#8 are listed in the
`Crypto.IO.PKCS8` module (see ``wrap_algo`` parameter).
:Return: A byte string with the encoded public or private half
of the key.
:Raise ValueError:
When the format is unknown or when you try to encrypt a private
key with *DER* format and PKCS#1.
:attention:
If you don't provide a pass phrase, the private key will be
exported in the clear!
.. _RFC1421: http://www.ietf.org/rfc/rfc1421.txt
.. _RFC1423: http://www.ietf.org/rfc/rfc1423.txt
.. _`PKCS#1`: http://www.ietf.org/rfc/rfc3447.txt
.. _`PKCS#8`: http://www.ietf.org/rfc/rfc5208.txt
"""
if passphrase is not None:
passphrase = tobytes(passphrase)
if format=='OpenSSH':
2014-12-05 08:12:51 -05:00
eb, nb = [self._key[comp].to_bytes() for comp in 'e', 'n']
if bord(eb[0]) & 0x80: eb=bchr(0x00)+eb
if bord(nb[0]) & 0x80: nb=bchr(0x00)+nb
keyparts = [ b('ssh-rsa'), eb, nb ]
keystring = b('').join([ struct.pack(">I",len(kp))+kp for kp in keyparts])
return b('ssh-rsa ')+binascii.b2a_base64(keystring)[:-1]
# DER format is always used, even in case of PEM, which simply
# encodes it into BASE64.
if self.has_private():
binary_key = newDerSequence(
0,
self.n,
self.e,
self.d,
self.p,
self.q,
self.d % (self.p-1),
self.d % (self.q-1),
2014-12-05 08:12:51 -05:00
Integer(self.q).inverse(self.p)
).encode()
if pkcs==1:
keyType = 'RSA PRIVATE'
if format=='DER' and passphrase:
raise ValueError("PKCS#1 private key cannot be encrypted")
else: # PKCS#8
if format=='PEM' and protection is None:
keyType = 'PRIVATE'
binary_key = PKCS8.wrap(binary_key, oid, None)
else:
keyType = 'ENCRYPTED PRIVATE'
if not protection:
protection = 'PBKDF2WithHMAC-SHA1AndDES-EDE3-CBC'
binary_key = PKCS8.wrap(binary_key, oid, passphrase, protection)
passphrase = None
else:
keyType = "RSA PUBLIC"
binary_key = newDerSequence(
algorithmIdentifier,
newDerBitString(
newDerSequence( self.n, self.e )
)
).encode()
if format=='DER':
return binary_key
if format=='PEM':
pem_str = PEM.encode(binary_key, keyType+" KEY", passphrase, self._randfunc)
return tobytes(pem_str)
raise ValueError("Unknown key format '%s'. Cannot export the RSA key." % format)
class RSAImplementation(object):
"""
An RSA key factory.
This class is only internally used to implement the methods of the `Crypto.PublicKey.RSA` module.
:sort: __init__,generate,construct,importKey
:undocumented: _g*, _i*
"""
def __init__(self, **kwargs):
"""Create a new RSA key factory.
:Keywords:
default_randfunc : callable
Specify how to collect random data:
- *None* (default). Use Random.new().read().
- not *None* . Use the specified function directly.
"""
2014-12-05 08:12:51 -05:00
self._default_randfunc = kwargs.get('default_randfunc', Random.new().read)
def generate(self, bits, randfunc=None, e=65537):
"""Randomly generate a fresh, new RSA key.
:Parameters:
bits : int
Key length, or size (in bits) of the RSA modulus.
It must be a multiple of 256, and no smaller than 1024.
randfunc : callable
Random number generation function; it should accept
a single integer N and return a string of random data
N bytes long.
If not specified, a new one will be instantiated
from ``Crypto.Random``.
e : int
Public RSA exponent. It must be an odd positive integer.
It is typically a small number with very few ones in its
binary representation.
The default value 65537 (= ``0b10000000000000001`` ) is a safe
choice: other common values are 5, 7, 17, and 257.
:attention: You should always use a cryptographically secure random number generator,
such as the one defined in the ``Crypto.Random`` module; **don't** just use the
current time and the ``random`` module.
:attention: Exponent 3 is also widely used, but it requires very special care when padding
the message.
:Return: An RSA key object (`_RSAobj`).
:Raise ValueError:
When **bits** is too little or not a multiple of 256, or when
**e** is not odd or smaller than 2.
"""
if bits < 1024 or (bits & 0xff) != 0:
raise ValueError("RSA modulus length must be a multiple of 256 and >= 1024")
if e%2==0 or e<3:
raise ValueError("RSA public exponent must be a positive, odd integer larger than 2.")
2014-12-05 08:12:51 -05:00
if randfunc is None:
randfunc = self._default_randfunc
e = Integer(e)
# Generate the prime factors of n
p = q = n = Integer(1)
size_p = bits >> 1
size_q = bits - size_p
while n.size_in_bits() != bits:
def totient_coprime_to_e(candidate):
return (candidate - 1).gcd(e) == 1
2014-12-05 08:12:51 -05:00
# Note that q might be one bit longer than p if somebody specifies an odd
# number of bits for the key. (Why would anyone do that? You don't get
# more security.)
p = generate_probable_prime(exact_bits=size_p,
randfunc=randfunc,
prime_filter=totient_coprime_to_e)
2014-12-05 08:12:51 -05:00
q = generate_probable_prime(exact_bits=size_q,
randfunc=randfunc,
prime_filter=totient_coprime_to_e)
2014-12-05 08:12:51 -05:00
n = p * q
# It's OK for p to be larger than q, but let's be
# kind to the function that will invert it for
# th calculation of u.
if p > q:
p, q = q, p
u = p.inverse(q)
d = e.inverse((p - 1) * (q - 1))
key_dict = dict(zip(('n', 'e', 'd', 'p', 'q', 'u'),
(n, e, d, p, q, u)))
return _RSAobj(key_dict, randfunc)
2014-06-11 15:46:22 +02:00
def construct(self, tup, consistency_check=True):
"""Construct an RSA key from a tuple of valid RSA components.
The modulus **n** must be the product of two primes.
The public exponent **e** must be odd and larger than 1.
In case of a private key, the following equations must apply:
- e != 1
- p*q = n
- e*d = 1 mod (p-1)(q-1)
- p*u = 1 mod q
:Parameters:
tup : tuple
2014-06-11 15:46:22 +02:00
A tuple of long integers, with at least 2 and no
more than 6 items. The items come in the following order:
1. RSA modulus (n).
2. Public exponent (e).
3. Private exponent (d). Only required if the key is private.
4. First factor of n (p). Optional, but factor q must also
be present.
5. Second factor of n (q). Optional.
6. CRT coefficient, (1/p) mod q (u). Optional.
consistency_check : boolean
If *True*, the library will verify that the provided components
fulfil the main RSA properties.
:Raise ValueError:
When the key being imported fails the most basic RSA validity checks.
:Return: An RSA key object (`_RSAobj`).
"""
2014-12-05 08:12:51 -05:00
comp_names = 'n', 'e', 'd', 'p', 'q', 'u'
key_dict = dict(zip(comp_names, map(Integer, tup)))
n, e, d, p, q, u = [key_dict.get(comp) for comp in comp_names]
if d is not None:
if None in (p, q):
# Compute factors p and q from the private exponent d.
# We assume that n has no more than two factors.
# See 8.2.2(i) in Handbook of Applied Cryptography.
ktot = d * e - 1
# The quantity d*e-1 is a multiple of phi(n), even,
# and can be represented as t*2^s.
t = ktot
while t % 2 ==0:
t //= 2
# Cycle through all multiplicative inverses in Zn.
# The algorithm is non-deterministic, but there is a 50% chance
# any candidate a leads to successful factoring.
# See "Digitalized Signatures and Public Key Functions as Intractable
# as Factorization", M. Rabin, 1979
spotted = False
2014-12-05 08:12:51 -05:00
a = Integer(2)
while not spotted and a < 100:
k = Integer(t)
2014-12-05 08:12:51 -05:00
# Cycle through all values a^{t*2^i}=a^k
while k < ktot:
cand = pow(a, k, n)
# Check if a^k is a non-trivial root of unity (mod n)
if cand != 1 and cand != (n - 1) and pow(cand, 2, n) == 1:
# We have found a number such that (cand-1)(cand+1)=0 (mod n).
# Either of the terms divides n.
p = Integer(n).gcd(cand + 1)
spotted = True
2014-12-05 08:12:51 -05:00
break
k *= 2
# This value was not any good... let's try another!
a += 2
if not spotted:
raise ValueError("Unable to compute factors p and q from exponent d.")
# Found !
assert ((n % p) == 0)
q = n // p
if u is None:
u = p.inverse(q)
key_dict['p'] = p
key_dict['q'] = q
key_dict['u'] = u
# Build key object
key = _RSAobj(key_dict, self._default_randfunc)
# Very consistency of the key
2014-06-11 15:46:22 +02:00
fmt_error = False
if consistency_check:
# Modulus and public exponent must be coprime
2014-12-05 08:12:51 -05:00
fmt_error = e <= 1 or e >= n
fmt_error |= Integer(n).gcd(e) != 1
2014-06-11 15:46:22 +02:00
# For RSA, modulus must be odd
2014-12-05 08:12:51 -05:00
fmt_error |= not n & 1
2014-06-11 15:46:22 +02:00
2014-12-05 08:12:51 -05:00
if not fmt_error and key.has_private():
2014-06-11 15:46:22 +02:00
# Modulus and private exponent must be coprime
2014-12-05 08:12:51 -05:00
fmt_error = d <= 1 or d >= n
fmt_error |= Integer(n).gcd(d) != 1
2014-06-11 15:46:22 +02:00
# Modulus must be product of 2 primes
2014-12-05 08:12:51 -05:00
fmt_error |= (p * q != n)
fmt_error |= test_probable_prime(p) == COMPOSITE
fmt_error |= test_probable_prime(q) == COMPOSITE
2014-06-11 15:46:22 +02:00
# See Carmichael theorem
2014-12-05 08:12:51 -05:00
phi = (p - 1) * (q - 1)
lcm = phi // (p - 1).gcd(q - 1)
fmt_error |= (e * d % int(lcm)) != 1
2014-06-11 15:46:22 +02:00
if hasattr(key, 'u'):
# CRT coefficient
2014-12-05 08:12:51 -05:00
fmt_error |= u <= 1 or u >= q
fmt_error |= (p * u % q) != 1
2014-06-11 15:46:22 +02:00
else:
fmt_error = True
if fmt_error:
raise ValueError("Invalid RSA key components")
2014-12-05 08:12:51 -05:00
return key
def _importKeyDER(self, extern_key, passphrase, verify_x509_cert):
"""Import an RSA key (public or private half), encoded in DER form."""
try:
der = _decode_der(DerSequence, extern_key)
# Try PKCS#1 first, for a private key
if len(der) == 9 and der.hasOnlyInts() and der[0] == 0:
# ASN.1 RSAPrivateKey element
del der[6:] # Remove d mod (p-1),
# d mod (q-1), and
# q^{-1} mod p
2014-12-05 08:12:51 -05:00
der.append(Integer(der[4]).inverse(der[5])) # Add p^{-1} mod q
del der[0] # Remove version
return self.construct(der[:])
# Keep on trying PKCS#1, but now for a public key
if len(der) == 2:
try:
# The DER object is an RSAPublicKey SEQUENCE with
# two elements
if der.hasOnlyInts():
return self.construct(der[:])
# The DER object is a SubjectPublicKeyInfo SEQUENCE
# with two elements: an 'algorithmIdentifier' and a
# 'subjectPublicKey'BIT STRING.
# 'algorithmIdentifier' takes the value given at the
# module level.
# 'subjectPublicKey' encapsulates the actual ASN.1
# RSAPublicKey element.
if der[0] == algorithmIdentifier:
bitmap = _decode_der(DerBitString, der[1])
rsaPub = _decode_der(DerSequence, bitmap.value)
if len(rsaPub) == 2 and rsaPub.hasOnlyInts():
return self.construct(rsaPub[:])
except (ValueError, EOFError):
pass
# Try to see if this is an X.509 DER certificate
# (Certificate ASN.1 type)
if len(der) == 3:
from Crypto.PublicKey import _extract_sp_info
try:
sp_info = _extract_sp_info(der)
if verify_x509_cert:
raise NotImplementedError("X.509 certificate validation is not supported")
return self._importKeyDER(sp_info, passphrase, False)
except ValueError:
pass
# Try PKCS#8 (possibly encrypted)
k = PKCS8.unwrap(extern_key, passphrase)
if k[0] == oid:
return self._importKeyDER(k[1], passphrase, False)
except (ValueError, EOFError):
pass
raise ValueError("RSA key format is not supported")
def importKey(self, extern_key, passphrase=None, verify_x509_cert=True):
"""Import an RSA key (public or private half), encoded in standard
form.
:Parameter extern_key:
The RSA key to import, encoded as a byte string.
An RSA public key can be in any of the following formats:
- X.509 certificate (binary or PEM format)
- X.509 ``subjectPublicKeyInfo`` DER SEQUENCE (binary or PEM
encoding)
- `PKCS#1`_ ``RSAPublicKey`` DER SEQUENCE (binary or PEM encoding)
- OpenSSH (textual public key only)
An RSA private key can be in any of the following formats:
- PKCS#1 ``RSAPrivateKey`` DER SEQUENCE (binary or PEM encoding)
- `PKCS#8`_ ``PrivateKeyInfo`` or ``EncryptedPrivateKeyInfo``
DER SEQUENCE (binary or PEM encoding)
- OpenSSH (textual public key only)
For details about the PEM encoding, see `RFC1421`_/`RFC1423`_.
The private key may be encrypted by means of a certain pass phrase
either at the PEM level or at the PKCS#8 level.
:Type extern_key: string
:Parameter passphrase:
In case of an encrypted private key, this is the pass phrase from
which the decryption key is derived.
:Type passphrase: string
:Parameter verify_x509_cert:
When importing the public key from an X.509 certificate, whether
the certificate should be validated. **Since verification is not
yet supported, this value must always be set to False**.
This value is ignored if an X.509 certificate is not passed.
:Type verify_x509_cert: bool
:Return: An RSA key object (`_RSAobj`).
:Raise ValueError/IndexError/TypeError:
When the given key cannot be parsed (possibly because the pass
phrase is wrong).
.. _RFC1421: http://www.ietf.org/rfc/rfc1421.txt
.. _RFC1423: http://www.ietf.org/rfc/rfc1423.txt
.. _`PKCS#1`: http://www.ietf.org/rfc/rfc3447.txt
.. _`PKCS#8`: http://www.ietf.org/rfc/rfc5208.txt
"""
extern_key = tobytes(extern_key)
if passphrase is not None:
passphrase = tobytes(passphrase)
if extern_key.startswith(b('-----')):
# This is probably a PEM encoded key.
(der, marker, enc_flag) = PEM.decode(tostr(extern_key), passphrase)
if enc_flag:
passphrase = None
return self._importKeyDER(der, passphrase, verify_x509_cert)
if extern_key.startswith(b('ssh-rsa ')):
# This is probably an OpenSSH key
keystring = binascii.a2b_base64(extern_key.split(b(' '))[1])
keyparts = []
while len(keystring) > 4:
l = struct.unpack(">I", keystring[:4])[0]
keyparts.append(keystring[4:4 + l])
keystring = keystring[4 + l:]
2014-12-05 08:12:51 -05:00
e = Integer.from_bytes(keyparts[1])
n = Integer.from_bytes(keyparts[2])
return self.construct([n, e])
if bord(extern_key[0]) == 0x30:
# This is probably a DER encoded key
return self._importKeyDER(extern_key, passphrase,
verify_x509_cert)
raise ValueError("RSA key format is not supported")
#: `Object ID`_ for the RSA encryption algorithm. This OID often indicates
#: a generic RSA key, even when such key will be actually used for digital
#: signatures.
#:
#: .. _`Object ID`: http://www.alvestrand.no/objectid/1.2.840.113549.1.1.1.html
oid = "1.2.840.113549.1.1.1"
#: This is the standard DER object that qualifies a cryptographic algorithm
#: in ASN.1-based data structures (e.g. X.509 certificates).
algorithmIdentifier = DerSequence(
[DerObjectId(oid).encode(), # algorithm field
DerNull().encode()] # parameters field
).encode()
_impl = RSAImplementation()
#:
#: Randomly generate a fresh, new RSA key object.
#:
#: See `RSAImplementation.generate`.
#:
generate = _impl.generate
#:
#: Construct an RSA key object from a tuple of valid RSA components.
#:
#: See `RSAImplementation.construct`.
#:
construct = _impl.construct
#:
#: Import an RSA key (public or private half), encoded in standard form.
#:
#: See `RSAImplementation.importKey`.
#:
importKey = _impl.importKey
# vim:set ts=4 sw=4 sts=4 expandtab: