Skip to content

Commit

Permalink
Merge pull request #207 from myheroyuki/multiprime
Browse files Browse the repository at this point in the history
multiprime support
  • Loading branch information
myheroyuki committed Jan 30, 2024
2 parents 18f5faf + 14db374 commit 63772a6
Show file tree
Hide file tree
Showing 9 changed files with 429 additions and 55 deletions.
1 change: 1 addition & 0 deletions .gitignore
Expand Up @@ -3,6 +3,7 @@
.*.swp

/.idea/
/.vscode/

/dist/
/distribute*.tar.gz
Expand Down
5 changes: 3 additions & 2 deletions doc/compatibility.rst
Expand Up @@ -5,9 +5,10 @@ Compatibility with standards
.. index:: compatibility

Python-RSA implements encryption and signatures according to PKCS#1
version 1.5. This makes it compatible with the OpenSSL RSA module.
version 1.5. Additionally, Python-RSA implements multiprime encryption according to PKCS#1
version 2.1. This makes it largely compatible with the OpenSSL RSA module.

Keys are stored in PEM or DER format according to PKCS#1 v1.5. Private
Keys are stored in PEM or DER format according to PKCS#1 v2.1. Private
keys are compatible with OpenSSL. However, OpenSSL uses X.509 for its
public keys, which are not supported.

Expand Down
3 changes: 2 additions & 1 deletion doc/index.rst
Expand Up @@ -8,7 +8,8 @@ Welcome to Python-RSA's documentation!

Python-RSA is a pure-Python RSA implementation. It supports
encryption and decryption, signing and verifying signatures, and key
generation according to PKCS#1 version 1.5.
generation according to PKCS#1 version 1.5. Additionally, Python-RSA
implements multirime encryption according to PKCS#1 version 2.1.

If you have the time and skill to improve the implementation, by all
means be my guest. The best way is to clone the `Git
Expand Down
5 changes: 5 additions & 0 deletions doc/usage.rst
Expand Up @@ -40,6 +40,11 @@ Alternatively you can use :py:meth:`rsa.PrivateKey.load_pkcs1` and
... keydata = privatefile.read()
>>> privkey = rsa.PrivateKey.load_pkcs1(keydata)

Python-RSA also allows you to generate RSA keys with multiple primes:

>>> import rsa
>>> (pubkey, privkey) = rsa.newkeys(512, nprimes=3)


Time to generate a key
++++++++++++++++++++++
Expand Down
36 changes: 36 additions & 0 deletions rsa/core.py
Expand Up @@ -17,6 +17,8 @@
This is the actual core RSA implementation, which is only defined
mathematically on integers.
"""
import itertools
import typing


def assert_int(var: int, name: str) -> None:
Expand Down Expand Up @@ -51,3 +53,37 @@ def decrypt_int(cyphertext: int, dkey: int, n: int) -> int:

message = pow(cyphertext, dkey, n)
return message


def decrypt_int_fast(
cyphertext: int,
rs: typing.List[int],
ds: typing.List[int],
ts: typing.List[int],
) -> int:
"""Decrypts a cypher text more quickly using the Chinese Remainder Theorem."""

assert_int(cyphertext, "cyphertext")
for r in rs:
assert_int(r, "r")
for d in ds:
assert_int(d, "d")
for t in ts:
assert_int(t, "t")

p, q, rs = rs[0], rs[1], rs[2:]
exp1, exp2, ds = ds[0], ds[1], ds[2:]
coef, ts = ts[0], ts[1:]

M1 = pow(cyphertext, exp1, p)
M2 = pow(cyphertext, exp2, q)
h = ((M1 - M2) * coef) % p
m = M2 + q * h

Ms = [pow(cyphertext, d, r) for d, r in zip(ds, rs)]
Rs = list(itertools.accumulate([p, q] + rs, lambda x, y: x*y))
for R, r, M, t in zip(Rs[1:], rs, Ms, ts):
h = ((M - m) * t) % r
m += R * h

return m

0 comments on commit 63772a6

Please sign in to comment.