7f3fea26 by 周伟奇

add rsa

1 parent c675cc4b
build*
.idea
\ No newline at end of file
.idea
*.pem
*.cert
*.py[cod]
\ No newline at end of file
......
## 保护源码:py2so.py
## 鉴权与保护
### 0. 运行环境
- python3
- pip install -r requirements.txt
### 1. 鉴权(服务端): verify.py
- 生成公私钥对
```
python RSA/create_keys.py
```
- 根据过期日期(必须)和MAC地址(可选, en0),通过私钥加密,生成认证文件
- help text
```
❯ python RSA/encrypt.py -h
usage: encrypt.py [-h] -d DATE [-m MAC]
encrypt expire date & mac address with private key
optional arguments:
-h, --help show this help message and exit
-d DATE, --date DATE expire date. eg: 2020-06-06
-m MAC, --mac MAC mac address
```
- example
```
python RSA/encrypt.py -d 2021-01-12 -m 38:f9:d3:2e:c0:f3
```
- 项目使用
- 拷贝以下文件至项目
- 公钥:RSA/public.pem
- 认证文件:RSA/certification.cert
- 验证脚本:verify.py
- 使用验证脚本鉴权
```
from verify import verify
is_valid = verify(path_to_public_key, path_to_cert)
if is_valid:
print('verify success')
else:
print('verify failed')
```
### 2. 保护源码:py2so.py
- description
```angular2html
compile the .py to .so(Linux/Mac) or .pdy(Win)
```
- help text
```
❯ python py2so.py -h
......
PRIVATE_KEY_NAME = "private.pem"
PUBLIC_KEY_NAME = "public.pem"
CERT_NAME = "certification.cert"
SPLIT_CHAR = "+"
DEFAULT_MAC = 'pass'
import os
from Crypto.PublicKey import RSA
from consts import PRIVATE_KEY_NAME, PUBLIC_KEY_NAME
def create_keys(private_key_path, public_key_path):
keys = RSA.generate(bits=4096)
with open(private_key_path, "wb") as private_fp:
private_fp.write(keys.export_key('PEM'))
with open(public_key_path, "wb") as public_fp:
public_fp.write(keys.publickey().export_key('PEM'))
def main():
output_dir = os.path.dirname(os.path.abspath(__file__))
private_key_path = os.path.join(output_dir, PRIVATE_KEY_NAME)
public_key_path = os.path.join(output_dir, PUBLIC_KEY_NAME)
create_keys(private_key_path, public_key_path)
if __name__ == '__main__':
main()
import os
import random
import argparse
from datetime import datetime
from Crypto.PublicKey import RSA
from consts import PRIVATE_KEY_NAME, CERT_NAME, SPLIT_CHAR, DEFAULT_MAC
parser = argparse.ArgumentParser(description='encrypt expire date & mac address with private key')
parser.add_argument('-d', '--date', help='expire date. eg: 2020-06-06', required=True)
parser.add_argument('-m', '--mac', default=DEFAULT_MAC, help='mac address')
args = parser.parse_args()
def get_exponent_and_modulus(private_key_path):
with open(private_key_path, 'r') as private_fp:
private_key = RSA.import_key(private_fp.read())
return private_key.d, private_key.n
def get_encrypt_int(mac, expire_date):
encrypt_bytes = "{0}{3}{1}{3}{2}".format(mac, str(random.random()), expire_date, SPLIT_CHAR).encode('utf-8')
return int.from_bytes(encrypt_bytes, byteorder='big')
def main():
try:
expire_date = datetime.strptime(args.date, '%Y-%m-%d')
except Exception as e:
print('expire date format error. eg: 2020-06-06')
return
if datetime.today() >= expire_date:
print('expire date must later than today')
return
base_dir = os.path.dirname(os.path.abspath(__file__))
private_key_path = os.path.join(base_dir, PRIVATE_KEY_NAME)
output_path = os.path.join(base_dir, CERT_NAME)
encrypt_int = get_encrypt_int(args.mac, args.date)
d, n = get_exponent_and_modulus(private_key_path)
signature = pow(encrypt_int, d, n)
with open(output_path, 'wb') as fp:
fp.write(str(signature).encode("utf-8"))
if __name__ == '__main__':
main()
import os
from getmac import get_mac_address
from datetime import datetime
from Crypto.PublicKey import RSA
from consts import PUBLIC_KEY_NAME, CERT_NAME, SPLIT_CHAR, DEFAULT_MAC
def get_exponent_and_modulus(public_key_path):
with open(public_key_path, 'r') as public_fp:
public_key = RSA.import_key(public_fp.read())
return public_key.e, public_key.n
def get_signature(cert_path):
with open(cert_path, 'r') as fp:
signature = fp.read()
return int(signature)
def is_expire(expire_date_str):
expire_date = datetime.strptime(expire_date_str, '%Y-%m-%d')
if datetime.today() >= expire_date:
return True
return False
def is_valid_mac(mac):
if mac == DEFAULT_MAC:
return True
if mac == get_mac_address():
return True
return False
def verify(public_key_path, cert_path):
try:
e, n = get_exponent_and_modulus(public_key_path)
signature = get_signature(cert_path)
encrypt_int = pow(signature, e, n)
encrypt_str = encrypt_int.to_bytes(length=encrypt_int.bit_length() // 8 + 1, byteorder='big').decode()
mac, _, expire_date_str = encrypt_str.split(SPLIT_CHAR)
if is_expire(expire_date_str) or not is_valid_mac(mac):
return False
return True
except Exception as e:
print('verify error: {0}'.format(e))
return False
if __name__ == '__main__':
base_dir = os.path.dirname(os.path.abspath(__file__))
public_key_path = os.path.join(base_dir, PUBLIC_KEY_NAME)
cert_path = os.path.join(base_dir, CERT_NAME)
is_valid = verify(public_key_path, cert_path)
if is_valid:
print('verify success')
else:
print('verify failed')
Cython==0.29.21
pycryptodome==3.9.9
getmac==0.8.2
\ No newline at end of file
......
from getmac import get_mac_address
from datetime import datetime
from Crypto.PublicKey import RSA
SPLIT_CHAR = "+"
DEFAULT_MAC = "pass"
def get_exponent_and_modulus(public_key_path):
with open(public_key_path, 'r') as public_fp:
public_key = RSA.import_key(public_fp.read())
return public_key.e, public_key.n
def get_signature(cert_path):
with open(cert_path, 'r') as fp:
signature = fp.read()
return int(signature)
def is_expire(expire_date_str):
expire_date = datetime.strptime(expire_date_str, '%Y-%m-%d')
if datetime.today() >= expire_date:
return True
return False
def is_valid_mac(mac):
if mac == DEFAULT_MAC:
return True
if mac == get_mac_address():
return True
return False
def verify(public_key_path, cert_path):
try:
e, n = get_exponent_and_modulus(public_key_path)
signature = get_signature(cert_path)
encrypt_int = pow(signature, e, n)
encrypt_str = encrypt_int.to_bytes(length=encrypt_int.bit_length() // 8 + 1, byteorder='big').decode()
mac, _, expire_date_str = encrypt_str.split(SPLIT_CHAR)
if is_expire(expire_date_str) or not is_valid_mac(mac):
return False
return True
except Exception as e:
print('verify error: {0}'.format(e))
return False
Styling with Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!