回覆列表
  • 1 # 開發者技術前線

    一、生成公鑰、私鑰對

    使用openssl工具生成RSA公鑰、私鑰對。

    1.下載openssl工具。下載地址

    2.開啟 openssl 資料夾下的 bin 資料夾,執行 openssl.exe 檔案;

    3.生成RSA私鑰命令:

    這裡生成的金鑰檔案是2048位元。

    genrsa -out rsa_private_key.pem 2048

    4.生成RSA公鑰命令:

    注意,公鑰和私鑰是成對的,所以你在生成一個後,另一個的生成是基於前一個的檔名,否則生成的不是一對哦!!

    rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem

    生成後的檔案應該在你的使用者目錄下,或者在openssl的bin資料夾下(有時候在有時又不在,真是搞不懂,反正你就在這兩個地方都找一下,肯定在的)。

    5.這裡介紹一下RSA金鑰檔案的規律,檔名都是以.pem為字尾,生成的RSA金鑰,可以看到都是

    以-----BEGIN RSA PRIVATE KEY-----開頭,-----END RSA PRIVATE KEY-----結尾的沒有換行的字串,這個就是原始的 RSA 私鑰。

    二、安裝python支援的加密庫—pycryptodome

    我用的python3.6版本,網上搜了一下,在python3.6之前的版本大部分是用pycrypto來進行加密的,而在python3.6之後,因無人維護pycrypto,所以改名為pycryptodome,這個庫的強大之處在於,他是pycrypto庫的擴充套件,用起來更加方便,更靈活啊~~功能槓槓滴

    1.安裝pycryptodome

    如果你安裝了pip,那麼就很簡單了。

    pip3 install pycryptodome

    2.將金鑰檔案匯入到程式中。

    from Crypto.PublicKey import RSA

    # 讀取標準的rsa公私鑰pem檔案

    def load_rsa_file(fn):

    key = None

    try:

    key = RSA.importKey(open(fn).read())

    except Exception as err:

    print("匯入rsa的KEY檔案出錯", fn, err)

    return key

    # 標準字串金鑰轉rsa格式金鑰

    def rsa_key_str2std(skey):

    ret = None

    try:

    ret = RSA.importKey(skey)

    except Exception as err:

    print("字串金鑰轉rsa格式金鑰錯誤", skey, err)

    return ret

    3.RSA加密

    from Crypto.Cipher import PKCS1_OAEP

    # RSA_加密

    def rsa_enc(data, rsa_key):

    ciphertext = b""

    try:

    cipher = PKCS1_OAEP.new(rsa_key)

    ciphertext = cipher.encrypt(data)

    except Exception as err:

    print("RSA加密失敗", "", err)

    return ciphertext

    由於RSA在加密過程中,每次加密只能加密最大長度的字串,如果你的加密資料超長,在加密過程中需要分段加密,同理,解密也是分段解密的。

    1024位的證書,加密時最大支援117個位元組,解密時為128;

    2048位的證書,加密時最大支援245個位元組,解密時為256。

    加密時支援的最大位元組數:證書位數/8 -11(比如:2048位的證書,支援的最大加密位元組數:2048/8 - 11 = 245)

    其中,11位位元組為保留位元組。

    上面我的金鑰檔案是2048位元,所以加密分塊長度為245位元組。

    4.加密分塊

    # 根據key長度計算分塊大小

    def get_block_size(rsa_key):

    try:

    # RSA僅支援限定長度內的資料的加解密,需要分塊

    # 分塊大小block_reversed_size=11

    reserve_size = block_reversed_size

    key_size = rsa_key.size_in_bits()

    if (key_size % 8) != 0:

    raise RuntimeError("RSA 金鑰長度非法")

    # 金鑰用來解密,解密不需要預留長度

    if rsa_key.has_private():

    reserve_size = 0

    bs = int(key_size / 8) - reserve_size

    except Exception as err:

    print("計算加解密資料塊大小出錯", rsa_key, err)

    return bs

    # 返回塊資料

    def block_data(data, rsa_key):

    bs = get_block_size(rsa_key)

    for i in range(0, len(data), bs):

    yield data[i:i + bs]

    RSA在解密分段時與加密時用的分段大小無關,都是按照金鑰長度/8來分段解密的。

    5.RSA解密

    from Crypto.Cipher import PKCS1_OAEP

    # RSA解密

    def rsa_dec(data, rsa_key):

    ret_data = b""

    try:

    cipher = PKCS1_OAEP.new(rsa_key)

    ret_data = cipher.decrypt(data)

    except Exception as err:

    print("RSA解密失敗", "", err)

    return ret_data

    6.RSA簽名

    from Crypto.Signature import pkcs1_15

    from Crypto.Hash import SHA256

    # RSA簽名

    def rsa_sign(data, rsa_key):

    signature = ""

    try:

    h = SHA256.new(data)

    signature = pkcs1_15.new(rsa_key).sign(h)

    except Exception as err:

    print("RSA簽名失敗", "", err)

    return signature

    7.RSA驗簽名

    # RSA簽名驗證

    def rsa_sign_verify(data, sig, rsa_key):

    try:

    h = SHA256.new(data)

    pkcs1_15.new(rsa_key).verify(h, sig)

    ret = True

    except (ValueError, TypeError):

    ret = False

    return ret

    8.RSA加解密類(我將RSA加解密封裝成一個類,方便後續直接呼叫),完整程式碼如下:

    # -*- coding: utf-8 -*-

    import Crypto.Cipher as Cipher

    import Crypto.Signature as Sign

    import Crypto.Hash as Hash

    from Crypto.PublicKey import RSA

    from Crypto.Cipher import PKCS1_v1_5 as PKCS1_v1_5_cipper

    from Crypto.Signature import PKCS1_v1_5 as PKCS1_v1_5_sign

    from Crypto.Hash import SHA1

    class Rsa:

    """RSA加解密簽名類

    """

    def __int__(self, ciper_lib=PKCS1_v1_5_cipper, sign_lib=PKCS1_v1_5_sign, hash_lib=SHA1,

    pub_file=None, pri_file=None, pub_skey=None, pri_skey=None, pub_key=None, pri_key=None,

    reversed_size=11):

    # 加解密庫

    self.ciper_lib = ciper_lib

    self.sign_lib = sign_lib

    self.hash_lib = hash_lib

    # 公鑰金鑰

    if pub_key:

    self.pub_key = pub_key

    elif pub_skey:

    self.pub_key = RSA.importKey(pub_skey)

    elif pub_file:

    self.pub_key = RSA.importKey(open(pub_file).read())

    if pri_key:

    self.pri_key = pri_key

    elif pri_skey:

    self.pri_key = RSA.importKey(pri_skey)

    elif pri_file:

    self.pri_key = RSA.importKey(open(pri_file).read())

    # 分塊保留長度

    self.block_reversed_size = reversed_size

    # 根據key長度計算分塊大小

    def get_block_size(self, rsa_key):

    try:

    # RSA僅支援限定長度內的資料的加解密,需要分塊

    # 分塊大小

    reserve_size = self.block_reversed_size

    key_size = rsa_key.size_in_bits()

    if (key_size % 8) != 0:

    raise RuntimeError("RSA 金鑰長度非法")

    # 金鑰用來解密,解密不需要預留長度

    if rsa_key.has_private():

    reserve_size = 0

    bs = int(key_size / 8) - reserve_size

    except Exception as err:

    print("計算加解密資料塊大小出錯", rsa_key, err)

    return bs

    # 返回塊資料

    def block_data(self, data, rsa_key):

    bs = self.get_block_size(rsa_key)

    for i in range(0, len(data), bs):

    yield data[i:i + bs]

    # 加密

    def enc_bytes(self, data, key=None):

    text = b""

    try:

    rsa_key = self.pub_key

    if key:

    rsa_key = key

    cipher = self.ciper_lib.new(rsa_key)

    for dat in self.block_data(data, rsa_key):

    cur_text = cipher.encrypt(dat)

    text += cur_text

    except Exception as err:

    print("RSA加密失敗", data, err)

    return text

    # 解密

    def dec_bytes(self, data, key=None):

    text = b""

    try:

    rsa_key = self.pri_key

    if key:

    rsa_key = key

    cipher = self.ciper_lib.new(rsa_key)

    for dat in self.block_data(data, rsa_key):

    if type(self.ciper_lib) == Cipher.PKCS1_OAEP:

    cur_text = cipher.decrypt(dat)

    else:

    cur_text = cipher.decrypt(dat, "解密異常")

    text += cur_text

    except Exception as err:

    print("RSA解密失敗", data, err)

    return text

    # RSA簽名

    def sign_bytes(self, data, key=None):

    signature = ""

    try:

    rsa_key = self.pri_key

    if key:

    rsa_key = key

    h = self.hash_lib.new(data)

    signature = self.sign_lib.new(rsa_key).sign(h)

    except Exception as err:

    print("RSA簽名失敗", "", err)

    return signature

    # RSA簽名驗證

    def sign_verify(self, data, sig, key=None):

    try:

    rsa_key = self.pub_key

    if key:

    rsa_key = key

    h = self.hash_lib.new(data)

    self.sign_lib.new(rsa_key).verify(h, sig)

    ret = True

    except (ValueError, TypeError):

    ret = False

    return ret

    def main():

    pass

    if __name__ == "__main__":

    main()

  • 2 # 小小猿愛嘻嘻

    Python支援加密的方式非常多,有許多現成的庫和模組可以使用,下面我簡單介紹幾種常見的加密方式,感興趣的朋友可以自己嘗試一下,實驗環境win10+python3.6,主要內容如下:

    MD5加密

    這是一種使用非常廣泛的加密方式,不可逆的,在日常字串加密中經常會用到,下面我簡單介紹一下這種方式,主要用到Python自帶的模組hashlib,測試程式碼如下,先建立一個md5物件,然後直接加密就行:

    程式執行截圖如下,已經成功進行md5加密:

    雜湊加密

    這裡以SHA1(安全雜湊)為例,簡單介紹一下Python是如何進行雜湊加密的,也用到hashlib這個模組,測試程式碼如下,非常簡單,先建立sha1物件,然後直接加密就行,這裡也支援 SHA224,SHA256等加密方式:

    程式執行截圖如下,已經成功進行SHA1加密:

    DES加密

    這是一個分組加密演算法,解密和加密是同一個演算法,下面我簡單介紹一下這種方式,主要用到pycryptodome這個模組,windows平臺安裝的話,直接在cmd視窗輸入安裝命令“pip install pycryptodomex”就行,測試程式碼如下,需要單獨定義一個金鑰:

    程式執行截圖如下,已經成功進行DES加密和解密:

    AES加密

    這也是一種廣泛使用的加密方法,是對DES的改進和替代,下面我簡單介紹一下這種方式,也用到pycryptodome這個模組,測試程式碼如下,稍微有些複雜:

    程式執行截圖如下,已經成功進行AES加密解密:

    RSA加密

    這是一種非對稱加密演算法,在公開金鑰加密和電子商業中經常會用到,下面我簡單介紹一下這種方式,主要用到rsa這個模組,安裝的話,直接在cmd視窗輸入安裝命令“pip install rsa”就行,測試程式碼如下,需要單獨定義一個公鑰和私鑰:

    程式執行截圖如下,已經成功進行rsa加密和解密:

    至此,我們就完成了利用Python來進行加密。總的來說,整個過程不難,有現成的模組可以直接使用,只要你有一定的Python基礎,熟悉一下上面的程式碼和示例,很快就能掌握的,當然,你也可以自己來實現加密演算法,不過需要一定的數學基礎,感興趣的話,可以到網上搜一下相關教程,介紹的非常詳細,希望以上分享的內容能對你有所幫助吧,也歡迎大家評論、留言進行補充。

  • 中秋節和大豐收的關聯?
  • 混凝土外加劑註冊商標屬於哪一類?