Week40 - 各种安全性演算法的应用 - 窜改、抵赖实作 [高智能方程式系列]

本文章同时发布于:

MediumiT 邦帮忙

大家好,继上次Week39 - 各种安全性演算法的应用 - 窃听、电子欺骗实作之后,这次要介绍窜改抵赖的实作。

实作

以下实作大量参考Golang RSA encrypt and decrypt example与Golang: aes-256-cbc examples (with iv, blockSize)。

并且全部的範例都在此,请先 clone 下来会较好理解。

窜改(falsification)

还记得Week38 - 「窜改(falsification)是什么?」章节防範的方法吗?就是

与电子欺骗的解决方法相同,传输人员在资料上产生一笔独一无二的代码供另一端验证

接下来就要利用产生独一无二的代码来实作,方法有 2 种:

数位签章(Digital Signature):

拥有私钥与公钥 2 把钥匙公钥可以给任何人,私钥不可以给自己以外的人使用私钥产生代码,公钥验证代码

讯息识别码(Message authentication code):

拥有 1 把钥匙这把钥匙不可以给不够信任的人使用此钥匙来产生代码

小明早餐店阿姨如果不够信任彼此,会採用数位签章,因为採用讯息识别码的话,小明把钥匙给早餐店阿姨早餐店阿姨拿去冒名成小明就不好了,

使用数位签章加在原本的循序图串起来就会如下:

看看程式码,进入week40/spoofing/signature的资料夹:

$ cd week40/spoofing/signature

里头有以下档案:

.├── badGuyKey     : 坏人的私钥├── badGuyKey.pub : 坏人的公钥├── goodGuykey    : 小明的私钥├── goodGuykey.pub: 小明的公钥└── main.go       : 程式码

keykey.pub是透过ssh-keygen这个软体来产生的,使用以下指令可以产生一组RSA公私钥:

$ ssh-keygen -t rsa -f <key's name> -m peme.g.$ ssh-keygen -t rsa -f goodGuykey -m pem

输入后会询问是否要设定passphrase,这是一个安全密码,如果设定了,以后使用此私钥还要输入此安全密码才可使用,以增加安全性,此範例没有设定。

code 的方面主要可以看main的部分,注解有解释流程,搭配循序图会较好理解:

// 大量参考: https://gist.github.com/mfridman/c0c5ece512f63d429c4589196a1d4242package mainimport ("crypto""crypto/rand""crypto/rsa""crypto/sha512""crypto/x509""encoding/pem""fmt""io/ioutil""log")// LoadFile load the file to bytesfunc LoadFile(path string) []byte {content, err := ioutil.ReadFile(path)if err != nil {log.Fatal(err)}return content}// BytesToPrivateKey bytes to private keyfunc BytesToPrivateKey(priv []byte) *rsa.PrivateKey {block, _ := pem.Decode(priv)enc := x509.IsEncryptedPEMBlock(block)b := block.Bytesvar err errorif enc {log.Println("is encrypted pem block")b, err = x509.DecryptPEMBlock(block, nil)if err != nil {log.Fatal(err)}}key, err := x509.ParsePKCS1PrivateKey(b)if err != nil {log.Fatal(err)}return key}func main() {// 坏人的私钥badGuyPrivateKey := BytesToPrivateKey(LoadFile("./badGuyKey"))// 小明的私钥goodGuyPrivateKey := BytesToPrivateKey(LoadFile("./goodGuyKey"))// 小明的公钥,公钥可以透过私要来取得,所以这边就不在载入公钥档案了goodGuyPublicKey := goodGuyPrivateKey.PublicKey// 小明用自己的私钥对讯息签章messageBytes := []byte("小明餐点: 大冰奶")hash := sha512.New()hash.Write(messageBytes)hashed := hash.Sum(nil)// 小明用自己的私钥签名signature, err := rsa.SignPKCS1v15(rand.Reader, goodGuyPrivateKey, crypto.SHA512, hashed)if err != nil {panic(err)}// 小明的资料被坏人拦截,坏人开始伪造小明的讯息messageBytes = []byte("小明餐点: 大冰红")hash = sha512.New()hash.Write(messageBytes)hashed = hash.Sum(nil)// 坏人用自己的私钥签名,并非小明的signature, err = rsa.SignPKCS1v15(rand.Reader, badGuyPrivateKey, crypto.SHA512, hashed)if err != nil {panic(err)}// 早餐店阿姨取得小明的公钥,利用此公钥验证之后发现不是小明传的讯息err = rsa.VerifyPKCS1v15(&goodGuyPublicKey, crypto.SHA512, hashed, signature)if err != nil {fmt.Println("Two signatures are not the same. Error: ", err)return}}

小明早餐店阿姨如果够信任彼此,甚至他们可能是同一个系统,那就不必担心早餐店阿姨小明的钥匙做坏事了,故可採用讯息识别码

使用讯息识别码加在原本的循序图串起来就会如下:

看看程式码,进入week40/falsification/HMAC的资料夹:

$ cd week40/falsification/HMAC

里头有以下档案:

.└── main.go : 程式码

code 主要可以看main的部分,注解有解释流程,搭配循序图会较好理解:

package mainimport ("crypto/hmac""crypto/sha256""encoding/hex""fmt")func hmacSha256(data string, secret string) string {h := hmac.New(sha256.New, []byte(secret))h.Write([]byte(data))return hex.EncodeToString(h.Sum(nil))}func main() {sharedSecret := "小明与早餐店阿姨的共同钥匙"badGuySecret := "坏人的钥匙"meals := "小明餐点: 大冰红"// 小明利用与早餐店阿姨共同的钥匙产生HMACrequestHMAC := hmacSha256(meals, sharedSecret)// 坏人拦截小明的封包,利用自己的钥匙产生HMACrequestHMAC := hmacSha256(meals, badGuySecret)// 早餐店阿姨利用与小明共同的钥匙产生HMACtrueHMAC := hmacSha256(meals, sharedSecret)// 早餐店阿姨比对此两个HMAC,发现不同,故此讯息不是小明传送的if requestHMAC != trueHMAC {fmt.Println("Two HMACs are not the same.")return}}

抵赖(repudiation)

还记得上篇文章 - 「抵赖(repudiation)是什么?」章节防範的方法吗?就是

要求传输人员在资料上产生一笔独一无二的代码供另一端验证

接下来就要利用产生独一无二的代码来实作,由于在抵赖的情境中,小明就是坏人,所以早餐店阿姨小明本来就不够信任彼此,所以只可用 1 种方法:

数位签章(Digital Signature):

拥有私钥与公钥 2 把钥匙公钥可以给任何人,私钥不可以给自己以外的人使用私钥产生代码,公钥验证代码

使用数位签章加在原本的循序图串起来就会如下:

看看程式码,进入week40/repudiation/signature的资料夹:

$ cd week40/repudiation/signature

里头有以下档案:

.├── goodGuyKey├── goodGuyKey.pub├── key├── key.pub└── main.go

钥匙都是透过ssh-keygen产生,可以参考上方窜改(falsification)章节的讲解,就不赘述。

code 主要可以看main的部分,注解有解释流程,搭配循序图会较好理解:

// 大量参考: https://gist.github.com/mfridman/c0c5ece512f63d429c4589196a1d4242package mainimport ("crypto""crypto/rand""crypto/rsa""crypto/sha512""crypto/x509""encoding/pem""fmt""io/ioutil""log")// LoadFile load the file to bytesfunc LoadFile(path string) []byte {content, err := ioutil.ReadFile(path)if err != nil {log.Fatal(err)}return content}// BytesToPrivateKey bytes to private keyfunc BytesToPrivateKey(priv []byte) *rsa.PrivateKey {block, _ := pem.Decode(priv)enc := x509.IsEncryptedPEMBlock(block)b := block.Bytesvar err errorif enc {log.Println("is encrypted pem block")b, err = x509.DecryptPEMBlock(block, nil)if err != nil {log.Fatal(err)}}key, err := x509.ParsePKCS1PrivateKey(b)if err != nil {log.Fatal(err)}return key}func main() {goodGuyPrivateKey := BytesToPrivateKey(LoadFile("./goodGuyKey"))// 小明的公钥,公钥可以透过私要来取得,所以这边就不在载入公钥档案了goodGuyPublicKey := goodGuyPrivateKey.PublicKey// 小明用自己的私钥对讯息签章messageBytes := []byte("小明餐点: 大冰奶")hash := sha512.New()hash.Write(messageBytes)hashed := hash.Sum(nil)// 小明用自己的私钥签名signature, err := rsa.SignPKCS1v15(rand.Reader, goodGuyPrivateKey, crypto.SHA512, hashed)if err != nil {panic(err)}// 早餐店阿姨取得小明的公钥,验证后发现的确是小明,传送餐点回去给小明err = rsa.VerifyPKCS1v15(&goodGuyPublicKey, crypto.SHA512, hashed, signature)if err != nil {fmt.Println("Two signatures are not the same. Error: ", err)return}fmt.Println("Verify the signature is correct")// 小明获得餐点,并且吃完后开市赖帐// 早餐店阿姨说明当初`rsa.VerifyPKCS1v15`利用小明的公钥验证后的确是小明用私钥签章的,故证明小明确实有点过餐}

参考

Golang RSA encrypt and decrypt exampleGolang: aes-256-cbc examples (with iv, blockSize)How and when do I use HMAC?AES encryption of files in Go演算法图鉴

关于作者: 网站小编

码农网专注IT技术教程资源分享平台,学习资源下载网站,58码农网包含计算机技术、网站程序源码下载、编程技术论坛、互联网资源下载等产品服务,提供原创、优质、完整内容的专业码农交流分享平台。

热门文章