Skip to content
This repository was archived by the owner on Apr 20, 2025. It is now read-only.

Commit 63772a6

Browse files
authored
Merge pull request #207 from myheroyuki/multiprime
multiprime support
2 parents 18f5faf + 14db374 commit 63772a6

9 files changed

+429
-55
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
.*.swp
44

55
/.idea/
6+
/.vscode/
67

78
/dist/
89
/distribute*.tar.gz

doc/compatibility.rst

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,10 @@ Compatibility with standards
55
.. index:: compatibility
66

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

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

doc/index.rst

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@ Welcome to Python-RSA's documentation!
88

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

1314
If you have the time and skill to improve the implementation, by all
1415
means be my guest. The best way is to clone the `Git

doc/usage.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,11 @@ Alternatively you can use :py:meth:`rsa.PrivateKey.load_pkcs1` and
4040
... keydata = privatefile.read()
4141
>>> privkey = rsa.PrivateKey.load_pkcs1(keydata)
4242

43+
Python-RSA also allows you to generate RSA keys with multiple primes:
44+
45+
>>> import rsa
46+
>>> (pubkey, privkey) = rsa.newkeys(512, nprimes=3)
47+
4348

4449
Time to generate a key
4550
++++++++++++++++++++++

rsa/core.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
This is the actual core RSA implementation, which is only defined
1818
mathematically on integers.
1919
"""
20+
import itertools
21+
import typing
2022

2123

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

5254
message = pow(cyphertext, dkey, n)
5355
return message
56+
57+
58+
def decrypt_int_fast(
59+
cyphertext: int,
60+
rs: typing.List[int],
61+
ds: typing.List[int],
62+
ts: typing.List[int],
63+
) -> int:
64+
"""Decrypts a cypher text more quickly using the Chinese Remainder Theorem."""
65+
66+
assert_int(cyphertext, "cyphertext")
67+
for r in rs:
68+
assert_int(r, "r")
69+
for d in ds:
70+
assert_int(d, "d")
71+
for t in ts:
72+
assert_int(t, "t")
73+
74+
p, q, rs = rs[0], rs[1], rs[2:]
75+
exp1, exp2, ds = ds[0], ds[1], ds[2:]
76+
coef, ts = ts[0], ts[1:]
77+
78+
M1 = pow(cyphertext, exp1, p)
79+
M2 = pow(cyphertext, exp2, q)
80+
h = ((M1 - M2) * coef) % p
81+
m = M2 + q * h
82+
83+
Ms = [pow(cyphertext, d, r) for d, r in zip(ds, rs)]
84+
Rs = list(itertools.accumulate([p, q] + rs, lambda x, y: x*y))
85+
for R, r, M, t in zip(Rs[1:], rs, Ms, ts):
86+
h = ((M - m) * t) % r
87+
m += R * h
88+
89+
return m

0 commit comments

Comments
 (0)