首页 > 其他分享 >消息认证码

消息认证码

时间:2023-03-04 10:34:07浏览次数:50  
标签:认证码 pkt mac TCP MAC 消息 key print

消息认证码

消息认证码的输入包含:任意长度的消息,密钥(发送者和接收者共享).输出:固定长度的密钥。

消息认证码的主要功能:

  • 数据完整性:计算MAC时,将消息和密钥进行计算产生MAC值,若数据被第三方攻击者修改则计算的MAC值并不相同,这保证了数据的完整性。
  • 数据真实性:计算MAC时,由于密钥只有发送者和接收者共享,则保证了数据的真实性。若密钥被第三方攻击这窃取则就无法保障数据的真实性。
  • 密码验证:在某些情况下,MAC还可以用作用户密码的验证机制,当合法的用户数据正确密码时,系统可以提取正确的MAC,使用正确的密码和API key所所生成的MAC与存储在服务器上的MAC进行比较,就可以完成密码验证工作。

image-20230303171326746

消息认证码的几种攻击

  • 重放攻击

    攻击者截获网络上的MAC数据包,并将其重新发送到目标用户,欺骗目标用户相信这是合法的通信。比如:

    假设银行使用一个MAC来验证客户端的请求。每个请求都包含时间戳(防止重放攻击)。攻击者成功的截获了一个合法请求和对应的MAC值。在一段时间以后,攻击者重新发送原始请求和相同的MAC值。由于请求的时间戳被攻击者处理成和之前截获的请求时间戳相同。由于攻击者使用之前的MAC,使得银行无法区分新的请求是否已经被更改或者重放。
    

    实验:

    from scapy.all import *
    
    # Function for sending ARP reply packets
    def send_arp_reply(pkt):
        if pkt[ARP].op == 1:
            ether = Ether(dst=pkt[Ether].src, src=get_if_hwaddr(conf.iface))
            arp = ARP(op=2, hwsrc=get_if_hwaddr(conf.iface), psrc=pkt[ARP].pdst,
                      hwdst=pkt[ARP].hwsrc, pdst=pkt[ARP].psrc)
            pkt = ether / arp
            print("ARP Replying to: " + pkt[ARP].psrc)
            #sendp(pkt, inter=0.5, iface=conf.iface)
    
    # Function for sending ICMP packets
    def send_icmp(pkt):
        if pkt[IP].dst == get_if_addr(conf.iface):
            ip = IP(src=pkt[IP].dst, dst=pkt[IP].src)
            icmp = ICMP(type="echo-reply", id=pkt[ICMP].id,
                        seq=pkt[ICMP].seq, load=pkt[ICMP].load)
            pkt = ip / icmp
            print("ICMP Replying to: " + pkt[IP].dst)
            #send(pkt, iface=conf.iface)
    
    # Function for sending TCP packets
    def send_tcp(pkt):
        if pkt[TCP].flags == "S":
            ip = IP(src=pkt[IP].dst, dst=pkt[IP].src)
            tcp = TCP(sport=pkt[TCP].dport, dport=pkt[TCP].sport,
                      flags="SA", seq=pkt[TCP].ack, ack=pkt[TCP].seq+1)
            pkt = ip / tcp
            print("TCP Replying to: " + pkt[IP].dst + ":" + str(pkt[TCP].dport))
            #send(pkt, iface=conf.iface)
    
    # Capture and replay packets
    pkts = sniff(iface=conf.iface, filter="arp or icmp or tcp", count=10)
    
    for pkt in pkts:
        if pkt.haslayer(ARP):
            send_arp_reply(pkt)
        elif pkt.haslayer(ICMP):
            send_icmp(pkt)
        elif pkt.haslayer(TCP):
            send_tcp(pkt)
    

    在上面的代码中,使用了ARP,ICMP和TCP三种不同类型的数据包的处理函数。每种函数根据接收到的数据包构建新的数据包,并使用send或者sendp函数将其发送回网络中。在主程序中执行sniff函数捕获10个数据包,然后对每个数据包进行重放攻击,既实现的三个函数。

  • 中间人攻击

    攻击者伪装为合法的通信方,并试图截获或篡改数据包。

    下面这个实验使用scapy实现消息认证码的中间人攻击的一个简单案例,该脚本将获取网络上的数据包,篡改身份验证并重放。

    #!/usr/bin/env python
    
    from scapy.all import *
    import hashlib
    
    def modify_packet(packet):
        # 查找TCP层并检查它是否有有效的负载
        if packet.haslayer(TCP) and packet.haslayer(Raw):
            # 获取原始数据负载,即消息认证码(MAC)
            mac = str(packet[Raw])
    
            # 对mac进行修改或者破坏,以达到欺骗的目的
            # 我们在这里简单地将所有小写字母转换为大写字母
            modified_mac = mac.upper()
    
            # 通过计算SHA256哈希值更新修改后的MAC
            hash_object = hashlib.sha256(bytes(modified_mac, 'utf-8'))
            modified_mac_sha256 = hash_object.hexdigest().encode('utf-8')
    
            # 更新TCP和数据包中的MAC字段
            packet[TCP].seq += len(mac) - len(modified_mac)
            packet[Raw].load = modified_mac_sha256
    
            # 删除IP和TCP校验和以及长度字段,以便Scapy重新计算它们
            del(packet[IP].chksum)
            del(packet[TCP].chksum)
            del(packet[IP].len)
    
            print("Modified MAC: ", modified_mac)
            print("Modified MAC SHA256: ", modified_mac_sha256)
    
        return packet
    
    # 定义回调函数来嗅探和修改数据包
    def sniff_packets(pkt):
        # 对基于TCP的HTTP流量进行过滤
        if pkt.haslayer(TCP) and pkt.haslayer(Raw) and \
                (pkt[TCP].dport == 80 or pkt[TCP].sport == 80):
            modified_pkt = modify_packet(pkt)
            # 这里先注释掉
            #sendp(modified_pkt, iface="eth0")
    
    # 启动捕获器
    sniff(filter="tcp port 80", prn=sniff_packets)
    
    
  • 内部攻击

    当攻击者拿到系统内部权限时,攻击者获取到密钥,从而达到攻击的目的。

  • 差分攻击

    攻击者拥有2个或者多个有效的MAC输入,并试图推测出正确结果。这种攻击需要针对具体实现的算法进行分析。

    差分攻击需要对加密算法进行分析,在python中有HMAC库支持差分攻击,下面是一个简单的案例:

    import hashlib
    import hmac
    
    def diff_attack(key, data, output):
        for a in range(256):
            for b in range(256):
                key1 = bytes([key[0] ^ a]) + key[1:]
                key2 = bytes([key[1] ^ b]) + key[2:]
                if hmac.new(key1, data, hashlib.sha256).digest() == output:
                    return (a, b, key2)
        return None
    
    # example usage
    key = b'\x01\x23\x45\x67\x89\xab\xcd\xef\xfe\xdc\xba\x98\x76\x54\x32\x10'
    data = b'Test Data'
    output = hmac.new(key, data, hashlib.sha256).digest()
    
    result = diff_attack(key, data, output)
    if result:
        print('Key byte 1: {:02X}'.format(result[0]))
        print('Key byte 2: {:02X}'.format(result[1]))
        print('Recovered key: {}'.format(result[2].hex().upper()))
    else:
        print('Key not found')
    

    上面的代码使用hmac库来计算SHA-256 HMAC,并通过枚举查找与给定输出匹配的密钥字节。

    消息认证码的实现原理

    • 密钥生成算法(Gen):

      输入:安全参数n, 输出: 满足特定分布的密钥k

    • 消息验证码子算法(Mac)

      输入:密钥k, 消息m; 输出:MAC标签t, \(Mac(k, m) \to k\)

    • 验证子算法(Vrfy)

      输入: 密钥k, 消息m, 标签t; 输出:\(b = Vrfy(k, m, t)\)

      其中b=1则认证成功,否则失败

    消息认证码的消息验证码子算法\(Mac(k, m)\)有两个方法:

    • 单向散列函数(\(HMAC\))的实现
    • 分组密码

单向散列函数HMAC

\[HMAC(k, m)=H((k\ XOR\ opad)+H(k\ XOR\ ipad)+m) \]

其中:k是密钥,m是认证消息,XOR是异或运算,opad是外部的填充常数,ipad是内部的填充常数,“+”是连接, H()是哈希函数,比如MD5,SHA1,SHA256等。

md5:		128位二进制(被破解)
sha1:		160位二进制(被破解)
sha256:	256位二进制(未破解)
  • MD5-MAC

    import hmac
    from hashlib import md5
    
    # 此处的 "message" 是要进行消息认证的内容
    message = b'This is a secret message'
    
    # 此处的 "key" 用于HMAC的计算 (应该保密)
    key = b'secret_key'
    
    # 创建 HMAC 对象
    hmac_md5 = hmac.new(key, message, md5)
    
    # 执行消息认证并输出结果
    print("HMAC-MD5 digest: {}".format(hmac_md5.digest()))
    
  • SHA1-MAC

    import hmac
    import hashlib
    
    KEY = b"secret_key"
    MESSAGE = b"my_message"
    
    # 使用SHA1算法创建HMAC
    digest_maker = hmac.new(KEY, MESSAGE, hashlib.sha1)
    
    # 输出HMAC十六进制表示形式的字符串
    print(digest_maker.hexdigest())
    
  • SHA256-MAC

分组密码

  • CBC-MAC

    加密过程:

    image-20230304094559363

    解密过程:

    image-20230304094630363

    CBC-MAC的消息认证公式如下:

    \[H_1 \gets E_k(x_1)\\ H_i \gets E_k(H_{i-1}+x_i),\ 2 \le i \le t \]

    实验:

    from scapy.all import *
    msg = b"Hello, this is a test message"
    
    # 创建一个加密密钥并将其设置为变量
    key = [0x24, 0x75, 0xa2, 0xb3, 0xc9, 0xf1, 0xed, 0xce]
    

    我们需将此消息进行cbc-mac计算。在发送之前,需要对其进行填充以确保其长度是AES块大小的倍数(在本例中为16字节)。代码如下:

    pad_len = (-len(msg)) % 16               # 计算填充长度
    cmac_msg = msg + bytes([pad_len])*pad_len # 添加一个填充以得到到达16字节长度的数据块
    iv = bytes([0] * 16)
    

    使用pyaes库来计算经过CBC-MAC处理后的数据块,利用循环使整个信息经过处理:

    import pyaes
    aes = pyaes.AES(bytes(key))
    
    # 对处理后的信号作出循环
    for i in range(0,len(cmac_msg),16):
        block = cmac_msg[i:i+16]
        iv = aes.encrypt(block_xor(iv, block))
    
    cmac_result = iv
    print(cmac_result.hex())
    

参考博客

标签:认证码,pkt,mac,TCP,MAC,消息,key,print
From: https://www.cnblogs.com/ALINGMAOMAO/p/17177772.html

相关文章