天天看點

加密解密之Token令牌

一、base64

(1). base64加密解密方法圖示

方法 作用 參數 傳回值
b64encode 将輸入的參數轉化為base64規則的串 預加密的明文,類型為bytes;例:b‘steve Jobs’ base64對應編碼的密文,類型為bytes;例:b’c3RldmUgSm9icw==’
b64decode 将base64串解密回明文 base64密文,類型為bytes;例:b’c3RldmUgSm9icw==’ 參數對應的明文,類型為bytes;例:b’steve Jobs’
urlsafe_b64encode 作用同b64encode,但是會将 ‘+‘替換成 ‘-’,将’/‘替換成’_’ 同b64encode 同b64encode
urlsafe_b64decode 作用同b64decode 同b64decode 同b64decode

(2). base64加密解密代碼示範

import base64
#無論是encode還是decode都需要位元組串
s = b"steve_Jobs"
base64_bs = base64.b64encode(s) #base64加密位元組串
print(base64_bs) #b'c3RldmVfSm9icw=='

decrypt_s = base64.b64decode(base64_bs)  #base64解密位元組串
print(decrypt_s) #b'steve_Jobs'

           

二、SHA-256

1.簡述

SHA256 是安全散列(hash)算法的一種,hash加密解密算法有三大特點如下:

(1). 定長,即無論輸入多長,加密後的輸出長度恒定;

(2). 不可逆,加密後的資訊不可逆推;

(3). 雪崩,隻有原資訊有稍微修改,加密輸出都會發生巨大改變;

2.SHA256加密代碼示範

import hashlib
sha_obj = hashlib.sha256() #建立sha256對象
s = b'steve Jobs' #欲加密的位元組串
sha_obj.update(s) #添加欲加密(hash)的内容

#擷取加密(hash)結果 (二進制顯示)
# b'*\xb7\x93\xe1!\xe0\xc4c\x80\xcd\xba\x19\x87\xa0\xa5\xad
# \x9f\xc0GQ\xa0\xe8d\xc0s\xd3\xa9\x86p0q\x9f'
print(sha_obj.digest())

#擷取加密(hash)結果 (十六進制顯示)
# 2ab793e121e0c46380cdba1987a0a5ad9fc04751a0e864c073d3a9867030719f
print(sha_obj.hexdigest())
           

三、HMAC-SHA256

(1). 簡述

HMAC-SHA256 是一種通過特别計算方式産生消息認證碼的加密算法,使用了雜湊演算法的同時結合了一個加密密鑰;它可以用來保證資料的完整性,同時可以用來作為某個消息的身份驗證。

(2). HMAC-SHA256加密代碼示範

import hmac
#生成hmac對象
#第一個參數為加密的key,bytes類型,
#第二個參數為欲加密的串,bytes類型
#第三個參數為hmac的算法,指定為SHA256
hm = hmac.new(b'steve Jobs', b'123456', digestmod='SHA256') #擷取hmac對象hm
#擷取最終結果
#二進制展示
#b"\xf6/X=\xa7X\xfc\x1c,@\xc4\xf6\x18\x0c\x1f+\x0bX\x9fA\xbb\
#xfc\x9b\xb3\x03\xa3\xc9\xcc \xde\x1f'"
print(hm.digest())

#十六進制展示
#f62f583da758fc1c2c40c4f6180c1f2b0b589f41bbfc9bb303a3c9cc20de1f27
print(hm.hexdigest())

           

四、 JWT(json-web-token)

1.簡述

JWT有三部分組成,如下:

(1). header

頭部分,格式為字典,表明所使用的算法和token類别,代碼示範如下:

#alg代表要使用的算法
#typ表明該token的類别 - 此處必須為 大寫的 JWT
{'alg':'HS256', 'typ':'JWT'}
           

(2). payload

聲明(加密)部分,分為公有聲明與私有聲明。對于公有聲明,JWT提供了内置關鍵字用于描述常見的問題,此聲明部分均為可選項,使用者可根據自己需求按需添加key;對于私有聲明,使用者可根據自己業務需求,添加自定義的key;公共聲明和私有聲明均在同一個字典中,轉成json串并用base64加密,聲明部分代碼示範如下:

{
 'exp':xxx, #公有聲明 Expiration Time 此token的過期時間的時間戳
 'iss':xxx,#公有聲明 (Issuer) Claim 指明此token的簽發者
 'aud':xxx, #公有聲明(Audience) Claim 指明此token的簽發群體
 'iat':xxx, #公有聲明 (Issued At) Claim 指明此建立時間的時間

 'username': 'steve Jobs', #私有聲明
 'uid': '1'	#私有聲明
}
           

(3). signature

算法簽名,用于加密算法更好加密解密

2.JWT加密解密手寫代碼示範

import copy
import time
import hmac
import json
import base64


class Jwt():
    def __init__(self):
        pass

    @staticmethod
    def b64encode(jstr_obj):
        return base64.urlsafe_b64encode(jstr_obj).replace(b"=", b"")

    @staticmethod
    def b64decode(b_s):
        rem = len(b_s) % 4
        if rem > 0:
            b_s += b"=" * (4 - rem)
        return base64.b64decode(b_s)

    @staticmethod
    def encode(pyload, key, algorithm="HS256"):
        header = {"alg": algorithm, "typ": "Jwt"}
        header_jstr = json.dumps(header, sort_keys=True, separators=(",", ":"))
        header_bs = Jwt.b64encode(header_jstr.encode())
        my_pyload = copy.deepcopy(pyload)
        my_pyload_jstr = json.dumps(my_pyload, sort_keys=True, separators=(",", ":"))
        my_pyload_bs = Jwt.b64encode(my_pyload_jstr.encode())
        str1_bs = header_bs + b"." + my_pyload_bs
        if isinstance(key, str):
            key = key.encode()
        sign = hmac.new(key=key, msg=str1_bs, digestmod="SHA256")
        sign_bs = Jwt.b64encode(sign.digest())
        return str1_bs + b"." + sign_bs

    @staticmethod
    def decode(b_s, key,algorithm="HS256"):
        if algorithm == "HS256":
            header_bs, pyload_bs, sign_bs = b_s.split(b".")
            if isinstance(key, str):
                key = key.encode()
            str_bs = header_bs + b"." + pyload_bs
            new_sign = hmac.new(key=key, msg=str_bs, digestmod="SHA256")
            new_sign_bs = Jwt.b64encode(new_sign.digest())
            if sign_bs != new_sign_bs:
                print("Hello")
            pyload_jstr = Jwt.b64decode(pyload_bs)
            pyload = json.loads(pyload_jstr)
            exp = pyload["exp"]
            if time.time() > exp:
                #過期
                raise
            return pyload
        else:
            pass

if __name__ == "__main__":
    exp = time.time() + 100
    b_s = Jwt.encode(pyload={"username":"steve Jobs","exp":exp},key="123456",algorithm="HS256")
    #對'{"username":"qiu"}'加密後的位元組串:
    #b'eyJhbGciOiJIUzI1NiIsInR5cCI6Ikp3dCJ9.eyJleHAiOjE1ODQ1ODk3NzYuNTIxMDU4NiwidXNl
    # cm5hbWUiOiJzdGV2ZSBKb2JzIn0.D3iI6a1ReuHSyDa1B0P5U8knY2k-MH0Wihim-5RCnJg'
    print(b_s)
    #解密後的内容
    #{'exp': 1584591827.635661, 'username': 'steve Jobs'}
    pyload = Jwt.decode(b_s,key="123456",algorithm="HS256")
    print(pyload)
           

3.JWT加密解密原生代碼示範

#jwt庫安裝:pip3 install pyjwt -i https://pypi.tuna.tsinghua.edu.cn/simple
import jwt
import time
exp = time.time() + 100
key = "123456"
payload = {"username":"steve Jobs","exp":exp}

#擷取加密位元組串
#b'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWVybmFtZSI6InN0ZXZlIEpvYnMiLC
#JleHAiOjE1ODQ1OTE4NjkuMTY2Njk0fQ.bDjL7S08_-4JO_cRNYfsrVN8i-jDOoyHCWFTcBr7ssQ'
b_s = jwt.encode(payload=payload,key=key,algorithm="HS256")
print(b_s)

#擷取解密位元組串
#{'username': 'steve Jobs', 'exp': 1584591869.166694}
decrypt_s = jwt.decode(b_s,key=key,algorithms="HS256")
print(decrypt_s)