/
myrsa.py
150 lines (108 loc) · 4.33 KB
/
myrsa.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
# Python3
# pip install rsa
import base64
import hashlib
import rsa
from rsa import common, transform, core
from rsa.pkcs1 import _pad_for_signing
def newkeys(nbits=128):
if nbits > 4096:
print('[WARNING] nbits is too big, it will take a long time.')
if nbits < 128:
print('[WARNING] nbits is too small.')
pub_key, priv_key = rsa.newkeys(nbits)
pubkey = base64.b64encode(pub_key.save_pkcs1('DER')).decode()
prikey = base64.b64encode(priv_key.save_pkcs1('DER')).decode()
return pubkey, prikey
def encrypt(message, pubkey, encoding='utf8'):
assert isinstance(message, str), 'message must be a sting!'
assert isinstance(pubkey, str), 'pubkey must be a sting!'
pubder = base64.b64decode(pubkey)
pub_key = rsa.PublicKey.load_pkcs1(pubder, 'DER')
message = message.encode(encoding)
keylength = common.byte_size(pub_key.n)
block_length = keylength - 11
assert block_length > 0, 'nbits of key is to small, please set bigger then 128!'
crypto = b''
while message:
m = message[:block_length]
message = message[block_length:]
c = rsa.encrypt(m, pub_key)
crypto += c
crypto = base64.b64encode(crypto).decode()
return crypto
def decrypt(crypto, prikey, encoding='utf8'):
assert isinstance(crypto, str), 'crypto must be a sting!'
assert isinstance(prikey, str), 'prikey must be a sting!'
prider = base64.b64decode(prikey)
priv_key = rsa.PrivateKey.load_pkcs1(prider, 'DER')
crypto = base64.b64decode(crypto)
keylength = common.byte_size(priv_key.n)
message = b''
while crypto:
c = crypto[:keylength]
crypto = crypto[keylength:]
m = rsa.decrypt(c, priv_key)
message += m
message = message.decode(encoding)
return message
def sign(message, prikey, encoding='utf8'):
assert isinstance(message, str), 'message must be a sting!'
assert isinstance(prikey, str), 'prikey must be a sting!'
message = message.encode(encoding)
prider = base64.b64decode(prikey)
priv_key = rsa.PrivateKey.load_pkcs1(prider, 'DER')
message_hash = hashlib.md5(message).digest()
keylength = common.byte_size(priv_key.n)
block_length = keylength - 11
assert block_length > 0, 'nbits of key is to small, please set bigger then 128!'
signature = b''
while message_hash:
cleartext = message_hash[:block_length]
message_hash = message_hash[block_length:]
# ===== copy from rsa.pkcs1:sign_hash =====
padded = _pad_for_signing(cleartext, keylength)
payload = transform.bytes2int(padded)
encrypted = priv_key.blinded_encrypt(payload)
block = transform.int2bytes(encrypted, keylength)
signature += block
signature = base64.b64encode(signature).decode()
return signature
def verify(message, signature, pubkey, encoding='utf8'):
assert isinstance(message, str), 'message must be a sting!'
assert isinstance(signature, str), 'signature must be a sting!'
message = message.encode(encoding)
signature_full = base64.b64decode(signature)
pubder = base64.b64decode(pubkey)
pub_key = rsa.PublicKey.load_pkcs1(pubder, 'DER')
message_hash = hashlib.md5(message).digest()
keylength = common.byte_size(pub_key.n)
decrypted_hash = b''
while signature_full:
signature = signature_full[:keylength]
signature_full = signature_full[keylength:]
# ===== copy from rsa.pkcs1:verify =====
encrypted = transform.bytes2int(signature)
decrypted = core.decrypt_int(encrypted, pub_key.e, pub_key.n)
clearsig = transform.int2bytes(decrypted, keylength)
if clearsig[0:2] != b'\x00\x01':
return False
clearsig = clearsig[2:]
if b'\x00' not in clearsig:
return False
sep_idx = clearsig.index(b'\x00')
clearsig = clearsig[sep_idx + 1:]
decrypted_hash += clearsig
return decrypted_hash == message_hash
if __name__ == '__main__':
pubkey, prikey = newkeys()
print((pubkey, prikey))
message = 'Hello@世界'
crypto = encrypt(message, pubkey)
print(crypto)
message = decrypt(crypto, prikey)
print(message)
signature = sign(message, prikey)
print(signature)
verified = verify(message, signature, pubkey)
print(verified)