29. cryptography knowledge - message authentication code MAC-6-- 2019 Nian 12 Yue 19 Ri

1. The message authentication code

1.1 Message Authentication

A message authentication code (message authentication code) is a verify the integrity and authentication technique, three take the first letter of the word, referred to as the MAC.

1539176665517

  • Thinking improvement program?

    Starting from the hash function

    Data to be transmitted needs to be hashed, and the hash value transmitted together raw data

    When performing the required hashing step of introducing encrypted

    • Introducing a secret key data when alice hashed, their involvement hashing generates a hash value
    • bob parity data
      • After receipt of the original bob and hash value,
        • Processing the raw data: the original data to generate a hash value by hashing keys and algorithms
        • Hash value comparing: generating a hash value and the hash value received for comparison

1.2 message authentication code using the steps

1539177690828

  1. Prerequisites:
    • In one party generating a message authentication code and verification, there must be a secret key
    • The two sides agreed to use the same good hash function for data calculation
  2. Process:
    • sender:
      • Sending the original message Method
      • The original message generating a message authentication code
        • ((Original message) + secret key) * = hash function function (message authentication code)
      • Sends a message authentication code to each other
    • Recipient:
      • Receiving raw data
      • Receiving a Message Authentication Code
      • check:
        • (+ Keys received message) * = new hash function hash value
        • By comparing the new hash value and the hash value received

1.3 go to the message authentication code using

There is a package: crypto / hmac

func New(h func() hash.Hash, key []byte) hash.Hash
- 返回值: hash接口
- 参数1: 函数函数的函数名
  sha1.new
  md5.new
  sha256.new
- 参数2: 秘钥

第二步: 添加数据
type Hash interface {
// 通过嵌入的匿名io.Writer接口的Write方法向hash中添加更多数据,永远不返回错误
io.Writer
// 返回添加b到当前的hash值后的新切片,不会改变底层的hash状态
Sum(b []byte) []byte
// 重设hash为无数据输入的状态
Reset()
// 返回Sum会返回的切片的长度
Size() int
// 返回hash底层的块大小;Write方法可以接受任何大小的数据,
// 但提供的数据是块大小的倍数时效率更高
BlockSize() int
}
type Writer interface {
Write(p []byte) (n int, err error)
}
第三步: 计算散列值

1.4 message authentication code issues

  1. Malpractice
    • There are difficult issues key distribution
  2. Can not solve the problem
    • Can not prove that the third party
    • Not prevent denial

2. Digital Signatures

2.1 signature generation and verification

  1. signature
    • To its original data hashing -> hash value
    • Asymmetric encryption of the private key to encrypt the hash value -> Signature
    • The raw data and signatures be sent to the other party
  2. verification
    • Receive data
      • Raw data
      • digital signature
    • Digital signature, you need to use the public key to decrypt obtain a hash value
    • The raw data is hashed to obtain a new hash value

2.2 Asymmetric encryption and digital signatures

to sum up:

  1. data communication

    • Public key encryption, a private key to decrypt
    1. digital signature:
- 私钥加密, 公钥解密

2.3 digital signature method

1539177860475

2.4 uses RSA digital signature

  1. Generate a key pair using rsa

    1. Generate a key pair
    2. Serialization
    3. Save the file to disk
  2. Digitally signed using a private key

    1. Open the private key disk
    2. The contents of the private key file read
    3. Pem decoding the data using the obtained structure variable pem.Block
    4. x509 parses the data structure into a private key -> the obtained private key
    5. Create a hash object -> md5 / sha1
    6. Add data to hash object
    7. Hash value is calculated
    8. Rsa function uses the hash value of the signature
    func SignPKCS1v15(rand io.Reader, priv *PrivateKey, hash crypto.Hash, hashed []byte) (s []byte, err error)
    参数1: rand.Reader
    参数2: 非对称加密的私钥
    参数3: 使用的哈希算法
       crypto.sha1
       crypto.md5
    参数4: 数据计算之后得到的散列值
    返回值: 
       - s: 得到的签名数据
       - err: 错误信息
  3. The use of public key signature verification

    1. Open public key file, the contents of the file read - [] byte
    2. Use pem decoding -> structure variables obtained pem.Block
    3. X509 using the data pem.Block analyzing Bytes variable -> to give an interface
    4. The type assertion -> structure obtained public key
    5. Original message hash (consistent hashing and signing algorithm used) -> hash value
      1. Create a hash Interface
      2. adding data
      3. Hash
    6. Signature Verification - function of rsa
    func VerifyPKCS1v15(pub *PublicKey, hash crypto.Hash, hashed []byte, sig []byte) (err error)
    参数1: 公钥
    参数2: 哈希算法 -> 与签名使用的哈希算法一致
    参数3: 将原始数据进行哈希原始得到的散列值
    参数4: 签名的字符串
    返回值: 
           - nil -> 验证成功
           - !=nil -> 失败

2.5 elliptic curve digital signature using

Elliptic curve corresponding to go in the package: import "crypto / elliptic"

A digital signature using elliptic curve in go: import "crypto / ecdsa"

U.S. FIPS186-2 standard recommended five an elliptic curve on a prime field, the five prime modulus are:

P~192~ = 2^192^ - 2^64^ - 1

P~224~ = 2^224^ - 2^96^ + 1

P~256~ = 2^256^ - 2^224^ + 2^192^ - 2^96^ -1

P~384~ = 2^384^ - 2^128^ - 2^96^ + 2^32^ -1

P~512~ = 2^512^ - 1

  1. Symmetric secret key is generated and saved to disk

    1. Generate a key pair using ecdsa
    func GenerateKey(c elliptic.Curve, rand io.Reader) (priv *PrivateKey, err error)
    1. The private key is written to disk
      • Serialized using x509
    func MarshalECPrivateKey(key *ecdsa.PrivateKey) ([]byte, error)
    • The resulting string in sections pem.Block structural body

    block := pem.Block{

    Type : "描述....",

    Bytes : MarshalECPrivateKey返回值中的切片字符串,

    }

    • 使用pem编码

    pem.Encode();

    1. 将公钥写入磁盘
      • 从私钥中得到公钥
      • 使用x509进行序列化
    func MarshalPKIXPublicKey(pub interface{}) ([]byte, error)
    • 将得到的切片字符串放入pem.Block结构体中

    block := pem.Block{

    Type : "描述....",

    Bytes : MarshalECPrivateKey返回值中的切片字符串,

    }

    • 使用pem编码

    pem.Encode();

  2. 使用私钥进行数字签名

    1. 打开私钥文件, 将内容读出来 ->[]byte
    2. 使用pem进行数据解码 -> pem.Decode()
    3. 使用x509, 对私钥进行还原
    func ParseECPrivateKey(der []byte) (key *ecdsa.PrivateKey, err error)
    
    1. 对原始数据进行哈希运算 -> 散列值
    2. 进行数字签名
    func Sign(rand io.Reader, priv *PrivateKey, hash []byte) (r, s *big.Int, err error)
       - 得到的r和s不能直接使用, 因为这是指针
       应该将这两块内存中的数据进行序列化 -> []byte
       func (z *Int) MarshalText() (text []byte, err error)
    
  3. 使用公钥验证数字签名

    1. 打开公钥文件, 将里边的内容读出 -> []byte
    2. pem解码 -> pem.Decode()
    3. 使用x509对公钥还原
    func ParsePKIXPublicKey(derBytes []byte) (pub interface{}, err error)
    
    1. 将接口 -> 公钥
    2. 对原始数据进行哈希运算 -> 得到散列值
    3. 签名的认证 - > ecdsa
    func Verify(pub *PublicKey, hash []byte, r, s *big.Int) bool
       - 参数1: 公钥
       - 参数2: 原始数据生成的散列值
       - 参数3,4: 通过签名得到的连个点
       func (z *Int) UnmarshalText(text []byte) error
    

2.6 数字签名无法解决的问题

1539178819165

6. 消息认证码

"消息认证码 --- 消息被正确传送了吗?"

6.1 什么是消息认证码

  • Alice 和 Bob 的故事

    像以前一样,我们还是从一个Alice和Bob的故事开始讲起。不过,这一次Alice和Bob分别是两家银行,Alice银行通过网络向Bob银行发送了一条汇款请求,Bob银行收到的请求内容是:

    $$
    从账户A-5374 向账户B-6671汇款1000万元
    $$

    当然,Bob银行所收到的汇款请求内容必须与Alice银行所发送的内容是完全一致的。如果主动攻击者Mallory在中途将Alice银行发送的汇款请求进行了篡改,那么Bob银行就必须要能够识别出这种篡改,否则如果Mallory将收款账户改成了自己的账户,那么1000万元就会被盗走。

    话说回来,这条汇款请求到底是不是Alice银行发送的呢?有可能Alice银行根本就没有发送过汇款请求,而是由主动攻击者Mallory伪装成Alice银行发送的。如果汇款请求不是来自Alice银行,那么就绝对不能执行汇款。

    现在我们需要关注的问题是汇款请求(消息)的 “完整性" 和 “认证" 这两个性质。

    消息的完整性(integrity), 指的是“消息没有被篡改"这一性质,完整性也叫一致性。如果能够确认汇款请求的内容与Alice银行所发出的内容完全一致,就相当于是确认了消息的完整性,也就意味着消息没有被篡改。

    消息的认证(authentication)指的是“消息来自正确的发送者"这一性质。如果能够确认汇款请求确实来自Alice银行,就相当于对消息进行了认证,也就意味着消息不是其他人伪装成发送者所发出的。

    通过使用本章中要介绍的消息认证码,我们就可以同时识别出篡改和伪装,也就是既可以确认消息的完整性,也可以进行认证。

  • 什么是消息认证码

    消息认证码(message authentication code)是一种确认完整性并进行认证的技术,取三个单词的首字母,简称为MAC。

    消息认证码的输入包括任意长度的消息和一个发送者与接收者之间共享的密钥,它可以输出固定长度的数据,这个数据称为MAC值

    根据任意长度的消息输出固定长度的数据,这一点和单向散列函数很类似。但是单向散列函数中计算散列值时不需要密钥,而消息认证码中则需要使用发送者与接收者之间共享的密钥。

    要计算MAC必须持有共享密钥,没有共享密钥的人就无法计算MAC值,消息认证码正是利用这一性质来完成认证的。此外,和单向散列函数的散列值一样,哪怕消息中发生1比特的变化,MAC值也会产生变化,消息认证码正是利用这一性质来确认完整性的。

    消息认证码有很多种实现方法,大家可以暂且这样理解:消息认证码是一种与密钥相关联的单向散列函数。

                                                 **单向散列函数与消息认证码的比较**
    

    1538733638766

6.2 消息认证码的使用步骤

我们还是以Alice银行和Bob银行的故事为例,来讲解一下消息认证码的使用步骤:

1538733684992

  1. 发送者Alice与接收者Bob事先共享密钥。
  2. 发送者Alice根据汇款请求消息计算MAC值(使用共享密钥)。
  3. 发送者Alice将汇款请求消息和MAC值两者发送给接收者Bob。
  4. 接收者Bob根据接收到的汇款请求消息计算MAC值(使用共享密钥)。
  5. 接收者Bob将自己计算的MAC值与从Alice处收到的MAC值进行对比。
  6. 如果两个MAC值一致,则接收者Bob就可以断定汇款请求的确来自Alice(认证成功);如果不一致,则可以断定消息不是来自Alice(认证失败)。

6.3 HMAC

6.3.1 HMAC介绍

HMAC是一种使用单向散列函数来构造消息认证码的方法(RFC2104),其中HMAC的H就是Hash的意思。

HMAC中所使用的单向散列函数并不仅限于一种,任何高强度的单向散列函数都可以被用于HMAC,如果将来设计出新的单向散列函数,也同样可以使用。

使用SHA-I、MD5、RIPEMD-160所构造的HMAC,分别称为HMAC-SHA-1、HMAC-MD5和HMAC-RlPEMD。

            **使用HMAC通过秘钥将消息生成消息认证码的内部实现**:

1538733763591

通过上述流程我们可以看出,最后得到的MAC值,一定是一个和输入的消息以及密钥都相关的长度固定的比特序列。

6.3.2 Go中对HMAC的使用

需要使用的包

import "crypto/hmac"

使用的函数

func New(h func() hash.Hash, key []byte) hash.Hash
func Equal(mac1, mac2 []byte) bool
  1. hamc.New 函数
    • 参数1: 创建一个新的使用哈希校验算法的hash.Hash接口, 如:
      • md5.New()
      • sha1.New()
      • sha256.New()
    • 参数2: 使用的秘钥
    • 返回值: 通过该哈希接口添加数据和计算消息认证码
      • 添加数据: Write(p []byte) (n int, err error)
      • 计算结果: Sum(b []byte) []byte
  2. hmac.Equal 函数
    • 比较两个MAC是否相同

生成消息认证码:

// 生成消息认证码
func GenerateHMAC(src, key []byte) []byte {
    // 1. 创建一个底层采用sha256算法的 hash.Hash 接口
    myHmac := hmac.New(sha256.New, key)
    // 2. 添加测试数据
    myHmac.Write(src)
    // 3. 计算结果
    result := myHmac.Sum(nil)

    return result
}

重要函数说明

  1. 创建一个底层采用哈希算法的 hash.Hash 接口

    函数对应的包: "crypto/hmac"
    func New(h func() hash.Hash, key []byte) hash.Hash
        - 参数 h: 函数指针, 返回值为hash.Hash, 可以使用哈希算法对应的New方法, 如:
            -- md5.New
            -- sha1.New
            -- sha256.New
            -- sha256.New224
            -- sha512.New
            -- sha512.New384
        - 参数 key: 和数据进行混合运算使用的秘钥
        - 返回值: hash.Hash 接口
    

验证消息认证码

func VerifyHMAC(res, src, key []byte) bool {

    // 1. 创建一个底层采用sha256算法的 hash.Hash 接口
    myHmac := hmac.New(sha256.New, key)
    // 2. 添加测试数据
    myHmac.Write(src)
    // 3. 计算结果
    result := myHmac.Sum(nil)
    // 4. 比较结果
    return hmac.Equal(res, result)
}

重要函数说明:

  1. 比较两个MAC是否相同

    函数对应的包: "crypto/hmac"
    func Equal(mac1, mac2 []byte) bool
        - 参数 mac1, mac2: 通过哈希算法计算得到的消息认证码
        - 返回值: 如果mac1==mac2, 返回 true; 否则, 返回 false
    

测试代码

func HMacTest() {
    key := []byte("我是消息认证码秘钥")
    src := []byte("我是消息认证码测试数据")
    result := GenerateHMAC(src, key)
    final := VerifyHMAC(result, src, key)
    if final {
        fmt.Println("消息认证码认证成功!!!")
    } else {
        fmt.Println("消息认证码认证失败 ......")
    }
}

6.3 消息认证码的密钥配送问题

在消息认证码中,需要发送者和接收者之间共享密钥,而这个密钥不能被主动攻击者Mallory获取。如果这个密钥落入Mallory手中,则Mallory也可以计算出MAC值,从而就能够自由地进行篡改和伪装攻击,这样一来消息认证码就无法发挥作用了。

发送者和接收者需要共享密钥,这一点和我们介绍的对称加密很相似。实际上,对称加密的密钥配送问题在消息认证码中也同样会发生。关于秘钥的配送后边章节会介绍如何使用非对称加密的方式进行解决。

6.4 消息认证码无法解决的问题

假设发送者Alice要向接收者Bob发送消息,如果使用了消息认证码,接收者Bob就能够断定自己收到的消息与发送者Alice所发出的消息是一致的,这是因为消息中的MAC值只有用Alice和Bob之间共享的密钥才能够计算出来,即便主动攻击者Mallory篡改消息,或者伪装成Alice发送消息,Bob也能够识别出消息的篡改和伪装。

但是,消息认证码也不能解决所有的问题,例如“对第三方证明"和“防止否认",这两个问题就无法通过消息认证码来解决。下面我们来逐一解释一下。

6.4.1 对第三方证明

假设Bob在接收了来自Alice的消息之后,想要向第三方验证者Victor证明这条消息的确是Alice发送的,但是用消息认证码无法进行这样的证明,这是为什么呢?

首先,Victor要校验MAC值,就需要知道Alice和Bob之间共享的密钥。

假设Bob相信Victor, 同意将密钥告诉Victor,即便如此,Victor也无法判断这条消息是由Alice发送的,因为Victor可以认为:“即使MAC值是正确的,发送这条消息的人也不一定是Alice,还有可能是Bob。"

能够计算出正确MAC值的人只有Alice和Bob,在他们两个人之间进行通信时,可以断定是对方计算了MAC值,这是因为共享这个密钥的双方之中,有一方就是自己。然而,对于第三方Victor、Alice或Bob却无法证明是对方计算了MAC值,而不是自己。

Chapter 7 will use a digital signature to be introduced to prove to third parties can be achieved.

6.4.2 prevent denial

Suppose Bob receives the message containing the MAC value with the MAC value is Alice and Bob shared key calculated, so Bob can be determined this message is from Alice.

However, we have said above, Bob can not prove to the verifier Victor that, that is to say, the sender Alice can claim to Victor: ". I had not sent this message to Bob" Such behavior is called denial (repudiation ).

Alice can say, "This message is Bob own series," is "maybe the key is Bob Mallory active attacker to steal, but keep my keys go again" and so on. To put it plainly, it is that Alice and Bob got into a fight.

Even Bob MAC value to take the burden of proof, Victor Alice and Bob can not determine who is the right idea, that is, with a message authentication code does not prevent denial (nonrepudiatlon) .

6.5 summary

Message is a message authentication code to authenticate and verify the integrity of the art. By using shared between the sender and recipient of the key, it can be identified and presence or absence of tampering camouflage.

The message authentication code can use the HMAC-way hash function, symmetric encryption can be implemented, it will not be described.

Message authentication code, because the sender and receiver share the same key, and therefore can not produce proof of third-party and other issues can not be prevented denied. In the next chapter, we will introduce a digital signature can solve these problems.

Guess you like

Origin www.cnblogs.com/oneapple/p/12068358.html