RSA

Overview

>>> from tomcrypt import rsa

This module contains a Key class for encrypting, decrypting, signing, and verifying data with a RSA private or public key.

Padding

By default, encryption will use OAEP padding, and signing will use PSS padding.

For greater compatibility (e.g. with OpenSSL which does not support PSS padding via the openssl rsautl command), you can use PKCS1 padding by setting the keyword argument padding="v1.5" on many methods. If padding has already been applied, you can also use padding="none" to disable it entirely.

Hashing

By default the keys will use sha1 for part of the encryption padding, and sha512 for the signature, but these can be changed via the hash keyword arg on many methods.

Use

You can generate new keys:

>>> key = rsa.Key(1024)

Or you can load an existing key from a string:

>>> key = rsa.Key('''-----BEGIN RSA PRIVATE KEY-----
MIICXwIBAAKBgQv9V1DrxfhDt56rC1/i18HJE6x/SLs2xu5IDySxI0xhme8U6T6w
Ess275MacdQMSZh5MJl+8YRErwx6zOilDz8y2GDqKrsuMgAodkvfKAeQlQZp+IPZ
dJlRhoE1Lk/aHBOiqRGR75LufiTAbaDMG3NWM1SidE9qVZv3HsWJqQU7ywIDAQAB
AoGBBbw8ppMCco5CKf58RHQI7cQ4Sw3gRt4fLyD9TXoG/qS5tCp2oOwtMVSoKeA+
j0cJdYyTePnGopUQf5HGr4s1zew14Ks2/91J70MEiABvrvVv9ZfiLT1e9/U/HdYE
s9Vv4NOpStZHhTcUrQXtiEBG+8VQhCIeuW1J9XKT8gTa7A+xAkED/rTemeSV9hQa
r9gJ4IHWVgJSNMm4A3bWsEM2R9Dm0Iwif8R/RHHJrsHgTKukYOOwbW7RFHwh+QVU
fL4pXjVR9wJBAwBORpdlEgWAD4IQK0CR6w3htz7w3KrS6OuckEPItA+W9Edt1n/a
v8Q7FiIdoHWPI4qaCI1g1GlOCUyXtaJb780CQQDKdafzs0r0sjouQYiDB3EVCdSY
Wq6xEN+jeUrPoM1wz60suguv0w7oJ71tsDUUcT7GC0Ac3A4lrCZzo3mxCsE1AkEA
419G7tj/a1dJv6EPW82TNYl+FIdtlrRSMCAmZZkJCLAQ3O65kx7mr6kY1MHV0dSp
nQQW0dg9JGjuwZcILuNsZQJBAk1MSHz9q4Azr5F3y9gaKyPNJBVpqAyI8acQRoJF
ioKaum9hlRf3nuXxmSfqv7iXozX6xfrYncjLKbBn/hPhWp8=
-----END RSA PRIVATE KEY-----''')

The public key is accessible via the public attribute, and the encoded version of a key is available via the as_string() method:

>>> pub = key.public
>>> print pub.as_string()
-----BEGIN PUBLIC KEY-----
MIGJAoGBC/1XUOvF+EO3nqsLX+LXwckTrH9IuzbG7kgPJLEjTGGZ7xTpPrASyzbvkxpx1AxJmHkw
mX7xhESvDHrM6KUPPzLYYOoquy4yACh2S98oB5CVBmn4g9l0mVGGgTUuT9ocE6KpEZHvku5+JMBt
oMwbc1YzVKJ0T2pVm/cexYmpBTvLAgMBAAE=
-----END PUBLIC KEY-----

You can see how large a payload a given key/padding/hash will support via the max_payload() method:

>>> key.max_payload() # using defaults
86
>>> key.max_payload(padding='none')
128

The reverse is also possible; calculating the key size required for a message payload of at least a given size:

>>> rsa.key_size_for_payload(100) # using defaults
1136
>>> rsa.key_size_for_payload(100, padding='none')
800

We can encrypt and decrypt:

>>> msg = b"Hello, World!"
>>> ct = key.encrypt(msg)
>>> pt = key.decrypt(ct)
>>> msg == pt
True

Note that you can encrypt with a public key, but you can’t decrypt:

>>> ct = pub.encrypt(msg)
>>> pt = pub.decrypt(ct)
Traceback (most recent call last):
<snip>
tomcrypt.LibError: A private PK key is required.

We can also sign/verify signatures:

>>> msg = b"Hello, World!"
>>> sig = key.sign(msg)
>>> key.verify(msg, sig)
True

Note that you can verify a signature with a public key, but you can’t sign:

>>> pub.verify(msg, sig)
True
>>> sig = pub.sign(msg)
Traceback (most recent call last):
<snip>
tomcrypt.LibError: A private PK key is required.

RSA API

class tomcrypt.rsa.Key

An RSA key.

This key can be imported from an encoded string, or randomly generated.

>>> # Generate a key.
>>> key = Key(1024)
>>> key.size
1024
>>> # Import a key.
>>> key = Key(open('/path/to/key.pem').read()) 
as_dict(radix=16)

Return a dict of all of the key parts encoded into strings.

Parameters:radix (int) – The base into which to convert the bignum; from 2 to 64.
as_string(type=None, format='pem')

Build the string representation of a key.

Both the availible formats are compatible with OpenSSL. We default to the same one that OpenSSL does (PEM).

Parameters:
  • type (str) – None (as is), 'private' or 'public'.
  • format (str) – 'pem' or 'der'.
>>> k = Key(1024)

>>> k.as_string() 
'-----BEGIN RSA PRIVATE KEY-----\n...\n-----END RSA PRIVATE KEY-----\n'

>>> k.public.as_string() 
'-----BEGIN PUBLIC KEY-----\n...\n-----END PUBLIC KEY-----\n'

>>> k.as_string(type='public') 
'-----BEGIN PUBLIC KEY-----\n...\n-----END PUBLIC KEY-----\n'

>>> isinstance(k.as_string(format='der'), bytes)
True
decrypt(input, hash='sha1', padding='oaep')

Decrypt some bytes.

Only usable on private keys.

Parameters:
  • input (bytes) – The bytes to decrypt.
  • padding (str) – One of 'none', 'v1.5', or 'oaep'.
  • hash – The hash that will be used: str or hash.Descriptor.
encrypt(input, prng='sprng', hash='sha1', padding='oaep')

Encrypt some bytes.

Parameters:
  • input (bytes) – The bytes to encrypt.
  • prng (str) – The PRNG to use; str or PRNG.
  • padding (str) – One of 'none', 'v1.5', or 'oaep'.
  • hash – The hash that will be used: str or hash.Descriptor.
is_private

True if this is a private key.

>>> k = Key(1024)
>>> k.is_private
True
>>> k.public.is_private
False
is_public

True if this is a public key.

>>> k = Key(1024)
>>> k.is_public
False
>>> k.public.is_public
True
max_payload(padding='oaep', hash='sha1')

The maximum length of the payload that is safe to encrypt/sign.

Parameters:
  • padding (str) – One of 'none', 'v1.5', 'oaep', or 'pss'.
  • hash – The hash that will be used: str or hash.Descriptor.

See also

max_payload() for examples.

public

A view of this key with only the public parts.

If this is already a public key, this will be the same object.

>>> k = Key(1024)
>>> a = k.public
>>> a.type
'public'
>>> b = k.public
>>> a is b
True
sign(input, prng='sprng', hash='sha512', padding='pss', saltlen=None)

Sign some bytes.

Only usable on private keys.

Parameters:
  • input (bytes) – The bytes to sign.
  • prng (str) – The PRNG to use; str or PRNG.
  • padding (str) – One of 'none', 'v1.5', or 'pss'.
  • hash – The hash that will be used: str or hash.Descriptor.
  • saltlen – Length of the salt, in bytes. By default, the strict maximum is used.
size

The bit length of the modulus of the key.

This will be a multiple of 8 for any key generated with this library, but that is not a requirement for others. (It is easy to make any size key with openssl, for instance.)

>>> Key(1024).size
1024
type

'private' or 'public'

>>> k = Key(1024)
>>> k.type
'private'
>>> k.public.type
'public'
verify(input, sig, hash='sha512', padding='pss', saltlen=None)

Verify the signature of some bytes.

Parameters:
  • input (bytes) – The bytes that were signed.
  • sig (bytes) – The signature.
  • padding (str) – One of 'none', 'v1.5', or 'pss'.
  • hash – The hash that will be used: str or hash.Descriptor.

Returns True if the signature is valid. Raises an exception if the signature is the wrong format.

tomcrypt.rsa.key_size_for_payload(length, padding='oaep', hash='sha1')

Determine the min keysize for a payload of a given length.

Parameters:
  • length (int) – The length of the payload.
  • padding (str) – One of 'none', 'v1.5', 'oaep', or 'pss'.
  • hash – The hash that will be used: str or hash.Descriptor.
>>> key_size_for_payload(86)
1024

>>> key_size_for_payload(128, padding='none')
1024
tomcrypt.rsa.max_payload(key_size, padding='oaep', hash='sha1')

Find the maximum length of the payload that is safe to encrypt/sign.

Parameters:
  • padding (str) – One of 'none', 'v1.5', 'oaep', or 'pss'.
  • hash – The hash that will be used: str or hash.Descriptor.
>>> max_payload(1024)
86
>>> max_payload(2048, hash='sha512')
126
>>> max_payload(1024, padding='none')
128

Table Of Contents

Previous topic

Pseudo-Random Number Generators (PRNGs)

Next topic

Elliptic Curve Crypto

This Page