ptrhon总结(十九):python模块(base64, struct, hashlib.md5 、sha1、hmac)

一、base64:

1.用记事本打开exejpgpdf这些文件时,我们都会看到一大堆乱码,因为二进制文件包含很多无法显示和打印的字符,所以,如果要让记事本这样的文本处理软件能处理二进制数据,就需要一个二进制到字符串的转换方法。Base64是一种最常见的二进制编码方法。

Base64编码会把3字节的二进制数据编码为4字节的文本数据

如果要编码的二进制数据不是3的倍数,最后会剩下1个或2个字节怎么办?Base64用\x00字节在末尾补足后,再在编码的末尾加上1个或2个=号,表示补了多少字节,解码的时候,会自动去掉。 

import base64
print(base64.b64encode(b'binary\x00string'))
print(base64.b64decode(b'YmluYXJ5AHN0cmluZw=='))
print(base64.b64encode(b'i\xb7\x1d\xfb\xef\xff'))
print(base64.urlsafe_b64encode(b'i\xb7\x1d\xfb\xef\xff'))
print(base64.urlsafe_b64decode('abcd--__'))

二、struct

1.准确地讲,Python没有专门处理字节的数据类型。但由于b'str'可以表示字节,所以,字节数组=二进制str。而在C语言中,我们可以很方便地用struct、union来处理字节,以及字节和int,float的转换。

>> 和 <<都是位运算,对二进制数进行移位操作。
<< 是左移,末位补0,类比十进制数在末尾添0相当于原数乘以10,x<<1是将x的二进制表示左移一位,相当于原数x乘2。比如整数4在二进制下是100,4<<1左移1位变成1000(二进制),结果是8。
>>是右移,右移1位相当于除以2。
而>>=和<<=,就是对变量进行位运算移位之后的结果再赋值给原来的变量,可以类比赋值运算符+=和-=可以理解。
比如x>>=2, 就是把变量x右移2位,再保留x操作后的值。

 \x:只是 16 进制的意思,后边跟两位,则表示单字节编码;\d:十进制;\o:八进制;

   对于 \xaa ⇒ chr(0xaa) ⇒ chr(16*a+a)

\u:unicode 码;

一般其后跟 4 个 16 进制数,因此,一般为 unicode-16
Python:字符串的decode和encode成员函数,可对其进行转换

>>> n = 10240099
>>> b1 = (n & 0xff000000) >> 24
>>> b2 = (n & 0xff0000) >> 16
>>> b3 = (n & 0xff00) >> 8
>>> b4 = n & 0xff
>>> bs = bytes([b1, b2, b3, b4])
>>> bs
b'\x00\x9c@c'

"""解释:
n & 0xff000000 = 10 000000
由于十六进制,一个数代表四位,
右移24位 后10 000000 =》10
"""

 2.structpack函数把任意数据类型变成bytes

>>> import struct
>>> struct.pack('>I', 10240099)
b'\x00\x9c@c'
"""
pack的第一个参数是处理指令,'>I'的意思是:

>表示字节顺序是big-endian,也就是网络序,I表示4字节无符号整数。
"""
#unpack把bytes变成相应的数据类型:
>>> struct.unpack('>IH', b'\xf0\xf0\xf0\xf0\x80\x80')
(4042322160, 32896)

三、hashlib

1.md5算法生成摘要

      MD5是最常见的摘要算法,速度很快,生成结果是固定的128 bit字节,通常用一个32位的16进制字符串表示。另一种常见的摘要算法是SHA1,调用SHA1和调用MD5完全类似。SHA1的结果是160 bit字节,通常用一个40位的16进制字符串表示。比SHA1更安全的算法是SHA256和SHA512,不过越安全的算法不仅越慢,而且摘要长度更长。

def test1():
    """update主要起拼接字符串作用"""
    import hashlib
    md5 = hashlib.md5()
    md5.update('how to use md5 in '.encode('utf-8'))
    md5.update('python hashlib?'.encode('utf-8'))
    print(md5.hexdigest())
def test2():
    """hexdigest()作用主要是生成16进制摘要"""
    import hashlib
    print(hashlib.md5("how to use md5 in python hashlib?".encode("utf8")).hexdigest())

2、对于用户来讲,当然不要使用过于简单的口令。但是,我们能否在程序设计上对简单口令加强保护呢?由于常用口令的MD5值很容易被计算出来,所以,要确保存储的用户口令不是那些已经被计算出来的常用口令的MD5,这一方法通过对原始口令加一个复杂字符串来实现,俗称“加盐”。经过Salt处理的MD5口令,只要Salt不被黑客知道,即使用户输入简单口令,也很难通过MD5反推明文口令。但是如果有两个用户都使用了相同的简单口令比如123456,在数据库中,将存储两条相同的MD5值,这说明这两个用户的口令是一样的。有没有办法让使用相同口令的用户存储不同的MD5呢?如果假定用户无法修改登录名,就可以通过把登录名作为Salt的一部分来计算MD5,从而实现相同口令的用户也存储不同的MD5。

例子:

# -*- coding: utf-8 -*-
import hashlib, random
def get_md5(s):
    return hashlib.md5(s.encode('utf-8')).hexdigest()
class User(object):
    def __init__(self, username, password):
        self.username = username
        self.salt = ''.join([chr(random.randint(48, 122)) for i in range(20)])
        """chr() 用一个范围在 range(256)内的(就是0~255)整数作参数,返回一个对应的字符。"""
        self.password = get_md5(password + self.salt)
db = {
    'michael': User('michael', '123456'),
    'bob': User('bob', 'abc999'),
    'alice': User('alice', 'alice2008')
}
def login(usrname, psw):
    user = db[usrname]
    return get_md5(psw + user.salt) == user.password
if __name__ == "__main__":
    print(login('michael', '123456'))
    print(login('bob', 'abc999'))
    print(login('alice', 'alice008'))

3.hmac加密算法

        HMAC加密算法是一种安全的基于加密hash函数和共享密钥的消息认证协议.它可以有效地防止数据在传输过程中被截获和篡改,维护了数据的完整性、可靠性和安全性. HMAC加密算法是一种基于密钥的报文完整性的验证方法,其安全性是建立在Hash加密算法基础上的。它要求通信双方共享密钥、约定算法、对报文进行Hash运算,形成固定长度的认证码。通信双方通过认证码的校验来确定报文的合法性。HMAC加密算法可以用来作加密、数字签名、报文验证等。

HMAC加密算法的定义

       HMAC加密算法是一种执行“校验和”的算法,它通过对数据进行“求和”来检查数据是否被更改了。在发送数据以前,HMAC加密算法对数据块和双方约定的公钥进行“散列操作”,以生成称为“摘要”的东西,附加在待发送的数据块中。当数据和摘要到达其目的地时,就使用HMAC加密算法来生成另一个校验和,如果两个数字相匹配,那么数据未被做任何篡改。否则,就意味着数据在传输或存储过程中被某些居心叵测的人作了手脚。

HMAC加密算法的定义用公式表示如下:

       HMAC(K,M)=H(K⊕opad∣H(K⊕ipad∣M))

       HMAC加密算法的加密步骤:

             (1) 在密钥K后面添加0来创建一个字长为B的字符串。(例如,如果K的字长是20字节,B=64字节,则K后会加入44个零字节0x00)

             (2) 将上一步生成的B字长的字符串与ipad做异或运算。

             (3) 将数据流text填充至第二步的结果字符串中。

             (4) 用H作用于第三步生成的数据流。

             (5) 将第一步生成的B字长字符串与opad做异或运算。

             (6) 再将第四步的结果填充进第五步的结果中。

             (7) 用H作用于第六步生成的数据流,输出最终结果 。

HMAC加密算法的典型应用

         HMAC加密算法的一个典型应用是用在“挑战/响应”(Challenge/Response)身份认证中,认证流程如下:

              (1) 先由客户端向服务器发出一个验证请求。

              (2) 服务器接到此请求后生成一个随机数并通过网络传输给客户端(此为挑战)。

              (3) 客户端将收到的随机数提供给ePass,由ePass使用该随机数与存储在ePass中的密钥进行HMAC-MD5运算并得到一个结果作为认证证据传给服务器(此为响应)。

              (4) 与此同时,服务器也使用该随机数与存储在服务器数据库中的该客户密钥进行HMAC-MD5运算,如果服务器的运算结果与客户端传回的响应结果相同,则认为客户端是一个合法用户 。

HMAC加密算法的安全性

          HMAC加密算法引入了密钥,其安全性已经不完全依赖于所使用的HASH算法,安全性主要有以下几点保证:

        (1)使用的密钥是双方事先约定的,第三方不可能知道。由上面介绍应用流程可以看出,作为非法截获信息的第三方,能够得到的信息只有作为“挑战”的随机数和作为“响应”的HMAC结果,无法根据这两个数据推算出密钥。由于不知道密钥,所以无法仿造出一致的响应。

        (2)在HMAC加密算法的应用中,第三方不可能事先知道输出(如果知道,不用构造输入,直接将输出送给服务器即可)。

       (3) HMAC加密算法与一般的加密重要的区别在于它具有“瞬时”性,即认证只在当时有效,而加密算法被破解后,以前的加密结果就可能被解密。

小知识之HMAC:

     HMAC是密钥相关的哈希运算消息认证码(Hash-based Message Authentication Code),HMAC运算利用哈希算法,以一个密钥和一个消息为输入,生成一个消息摘要作为输出。

def hmac():
    import hmac
    message = b'Hello, world!'
    key = b'secret'
    h = hmac.new(key, message, digestmod='MD5')
    print(h.hexdigest())

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值