Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
15 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions ExpandApplication/AsymmetricCiphers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
from fastecdsa import curve, ecdsa, keys
from fastecdsa.encoding.der import DEREncoder

message = "a message to sign via ECDSA" # 一些訊息

print("使用預設曲線P256跟雜湊函數SHA2")
private_key = keys.gen_private_key(curve.P256)
public_key = keys.get_public_key(private_key, curve.P256)
print("私密金鑰: " + str(private_key))
print("公開金鑰: " + str(public_key))
print(type(public_key))

print("產生數位簽章,為兩個整數r跟s")
r, s = ecdsa.sign(message, private_key)
print(r)
print(s)

print("編碼數位簽章,使用DEREncoder為r跟s做編碼以利傳輸")
encoded = DEREncoder.encode_signature(r, s)
b = "數位簽章: "
for i in encoded:
b += str(hex(i)) + " "
print(b)
decoded_r, decoded_s = DEREncoder.decode_signature(encoded)
valid = ecdsa.verify((decoded_r, decoded_s), message, public_key)
if r == decoded_r and s == decoded_s and valid:
print("成功")
150 changes: 150 additions & 0 deletions ExpandApplication/SymmetricCiphers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
import json
from base64 import b64encode
from base64 import b64decode
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad
from Crypto.Util.Padding import unpad
from Crypto.Random import get_random_bytes


class stream_ciphers():
def __init__(self, key=None, encrypt_method="aes-256-cfb", iv=None,
segment_size=8, nonce=None, initial_value=None,
counter=None):
self.__key = key
self.__encrypt_method = encrypt_method
self.__iv = iv
self.__segment_size = segment_size
self.__nonce = nonce
self.__initial_value = initial_value
self.__counter = counter
self.__items = None

def encrypt(self, message="test"):
"""aaa."""
cipher, iv, segment_size, nonce, initial_value, counter = next(
self.encrypt_method)
message = message.encode('utf8')
if self.__items[2] == "cfb":
ct_bytes = cipher.encrypt(pad(message, AES.block_size))
else:
ct_bytes = cipher.encrypt(message)

ct_b64 = b64encode(ct_bytes).decode('utf-8')

result = {
'iv': self.__iv,
'segment_size': self.__segment_size,
'nonce': self.__nonce,
'initial_value': self.__initial_value,
'counter': self.__counter,
'ciphertext': ct_b64,
}

result = json.dumps(result)
yield result.encode('utf8')

def decrypt(self, cipher_message):
# We assume that the key was securely shared beforehand
try:
cipher_message = cipher_message.encode('utf8')
b64 = json.loads(cipher_message)

iv = b64decode(b64['iv'])
segment_size = b64decode(b64['segment_size'])
nonce = b64decode(b64['nonce'])
initial_value = b64decode(b64['initial_value'])
counter = b64decode(b64['counter'])
ct = b64decode(b64['ciphertext'])

self.reset_encrypt_method(
key=self.__key,
encrypt_method=self.__encrypt_method,
iv=iv,
segment_size=segment_size,
nonce=nonce,
initial_value=initial_value,
counter=counter
)

cipher, iv, segment_size, nonce, initial_value, counter = next(
self.encrypt_method)

if self.__items[2] == "cfb":
pt = unpad(cipher.decrypt(ct), AES.block_size)
else:
pt = cipher.decrypt(ct)

yield pt

except:
print("Incorrect decryption")

@property
def encrypt_method(self):
if self.__key is None:
self.__key = get_random_bytes(16)
else:
self.__key = self.__key

if len(self.__key) % 8 != 0:
raise ValueError('金鑰長度必須是符合8的倍數')

self.__items = items = self.__encrypt_method.split("-")
if items[1] == len(self.__key) * 16:
raise ValueError('不符合金鑰設定的位元長度')

if items[0] == "aes":
if items[2] == "ecb":
cipher = AES.new(self.__key, AES.MODE_ECB)

elif items[2] == "cbc":
cipher = AES.new(self.__key, AES.MODE_CBC, iv=self.__iv)
self.__iv = b64encode(cipher.iv).decode('utf-8')

elif items[2] == "ctr":
cipher = AES.new(self.__key, AES.MODE_CTR, nonce=self.__nonce,
initial_value=self.__initial_value,
counter=self.__counter)
self.__nonce = b64encode(cipher.nonce).decode('utf-8')

elif items[2] == "cfb":
cipher = AES.new(self.__key, AES.MODE_CFB, iv=self.__iv,
segment_size=self.__segment_size)
self.__iv = b64encode(cipher.iv).decode('utf-8')

elif items[2] == "ofb":
cipher = AES.new(self.__key, AES.MODE_OFB, iv=self.__iv)
self.__iv = b64encode(cipher.iv).decode('utf-8')

elif items[2] == "openpgp":
cipher = AES.new(self.__key, AES.MODE_OPENPGP)

else:
raise ValueError('沒有此加密演算法')

else:
raise ValueError('沒有此加密演算法')

iv = self.__iv
segment_size = self.__segment_size
nonce = self.__nonce
initial_value = self.__initial_value
counter = self.__counter
yield cipher, iv, segment_size, nonce, initial_value, counter

def reset_encrypt_method(self, key=None, encrypt_method="aes-256-cfb",
iv=None, segment_size=None, nonce=None,
initial_value=None, counter=None):
self.__key = key
self.__encrypt_method = encrypt_method
self.__iv = iv
self.__segment_size = segment_size
self.__nonce = nonce
self.__initial_value = initial_value
self.__counter = counter


sc = stream_ciphers()
print(next(sc.encrypt()))
print(next(sc.encrypt()))
42 changes: 40 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,41 @@
# Talk
利用Python撰寫的點對點或中央談話程式。
Talk
===
利用Python撰寫的點對點或中央談話程式,可以選擇使用不同的加密演算法保護傳輸的資料。
Peer-to-peer or central talk program written in Python.

使用Python3.6,並且使用以下套件:
- fastecdsa
- pycryptodome
- socket

支援的加密演算法:
- 「對稱性加密演算法」(Symmetric ciphers)
- 「串流加密法」(Stream ciphers)
- ciphers
- ChaCha20
- XChaCha20
- Salsa20
- authentication (MAC)
- Poly1305
- 「區塊加密法」(Block ciphers)
- Ciphers
- AES
- Classic modes of operation
- ECB mode
- CBC mode
- CTR mode
- CFB mode
- OFB mode
- OpenPGP mode
- Modern modes of operation
- CCM mode
- EAX mode
- GCM mode
- SIV mode
- OCB mode

- 「非對稱性加密演算法」(Asymmetric ciphers):
- RSA
- ECC

- Hybrid ciphers:結合兩者