密码学奇妙之旅、02 混合加密系统、AES、RSA标准、Golang代码( 二 )


密码学奇妙之旅、02 混合加密系统、AES、RSA标准、Golang代码

文章插图

密码学奇妙之旅、02 混合加密系统、AES、RSA标准、Golang代码

文章插图
msg := []byte("verifiable message")//在签名之前,我们需要对我们的消息进行哈希处理msgHash := sha256.New()_, err = msgHash.Write(msg)if err != nil { panic(err)}msgHashSum := msgHash.Sum(nil)//为了生成签名,我们提供了一个随机数生成器,我们的私钥,我们使用的散列算法和消息的散列信息signature, err := rsa.SignPSS(rand.Reader, privateKey, crypto.SHA256, msgHashSum, nil)if err != nil { panic(err)}//为了验证签名,我们提供了公钥,散列算法,我们消息的哈希和和我们之前生成的签名//有一个可选的"选项"参数,现在可以省略err = rsa.VerifyPSS(&publicKey, crypto.SHA256, msgHashSum, signature, nil)if err != nil { fmt.Println("could not verify signature: ", err) return}//如果我们没有从 `VerifyPSS` 方法中得到任何错误,这意味着我们的签名有效fmt.Println("signature verified")代码aes_crypto.gopackage mainimport ( "crypto/aes" "crypto/cipher" "crypto/rand" "encoding/base64" "errors" "io")// ^ 生成会话密钥func AES_Key_Generator() []byte { var key []byte = make([]byte, 32) _, err := io.ReadFull(rand.Reader, key) CheckError(err) return key}func AES_Encrypt(key []byte, message string) (encoded string, err error) { //从输入字符串创建字节切片 plainText := []byte(message) //使用密钥创建新的 AES 密码 block, err := aes.NewCipher(key) //如果 NewCipher 失败,退出: CheckError(err) // ^ 使密文成为大小为 BlockSize + 消息长度的字节切片,这样传值后修改不会更改底层数组 cipherText := make([]byte, aes.BlockSize+len(plainText)) // ^ iv 是初始化向量 (16字节) iv := cipherText[:aes.BlockSize] if _, err = io.ReadFull(rand.Reader, iv); err != nil {return } // ^ 加密数据,给定加密算法用的密钥,以及初始化向量 stream := cipher.NewCTR(block, iv) stream.XORKeyStream(cipherText[aes.BlockSize:], plainText) return base64.RawStdEncoding.EncodeToString(cipherText), err}func AES_Decrypt(key []byte, secure string) (decoded string, err error) { //删除 base64 编码: cipherText, err := base64.RawStdEncoding.DecodeString(secure) //如果解码字符串失败,退出: CheckError(err) //使用密钥和加密消息创建新的 AES 密码 block, err := aes.NewCipher(key) //如果 NewCipher 失败,退出: CheckError(err) //如果密文的长度小于 16 字节 if len(cipherText) < aes.BlockSize {err = errors.New("密文分组长度太小")return } // ^ iv 是初始化向量 (16字节) iv := cipherText[:aes.BlockSize] cipherText = cipherText[aes.BlockSize:] //解密消息 stream := cipher.NewCTR(block, iv) stream.XORKeyStream(cipherText, cipherText) return string(cipherText), err}rsa_crypto.gopackage mainimport ( "crypto/rand" "crypto/rsa" "crypto/sha256" "encoding/base64" "fmt")func CheckError(e error) { if e != nil {fmt.Println(e.Error())panic(e) }}// ^ 生成密钥与公钥func RSA_Generator() (*rsa.PrivateKey, rsa.PublicKey) { privateKey, err := rsa.GenerateKey(rand.Reader, 2048) CheckError(err) return privateKey, privateKey.PublicKey}func RSA_OAEP_Encrypt(key rsa.PublicKey, secretMessage string) string { label := []byte("标签") ciphertext, err := rsa.EncryptOAEP(sha256.New(), rand.Reader, &key, []byte(secretMessage), label) CheckError(err) return base64.RawStdEncoding.EncodeToString(ciphertext)}func RSA_OAEP_Decrypt(privKey *rsa.PrivateKey, cipherText string) string { ct, _ := base64.RawStdEncoding.DecodeString(cipherText) label := []byte("标签") // ^ 解密过程中的 rand.Reader 不是必选的,但一般要提供用来防止 side channel attacks. plaintext, err := rsa.DecryptOAEP(sha256.New(), rand.Reader, privKey, ct, label) CheckError(err) return string(plaintext)}main.gopackage mainimport ( "bufio" "crypto/rsa" "encoding/base64" "fmt" "os" "strings")func main() { privateKey, publicKey := RSA_Generator() fmt.Printf("\n\t共同N: %v\n\t公钥E: %v\n\t私钥D: %v\n", publicKey.N, publicKey.E, privateKey.D) reader := bufio.NewReader(os.Stdin) var message string // 如果没有给运行附加参数 if len(os.Args) != 2 {fmt.Printf("\n\t获取不到程序运行附加参数,手动输入字符串\n")fmt.Printf("\t字符串:")message, _ = reader.ReadString('\n') } else {message = os.Args[1] } encrypted := hybridEncrypt(publicKey, message) //打印密钥和密文 fmt.Printf("\n\t加密后: %s\n", encrypted) //解密文本 decrypted := hybridDecrypt(privateKey, encrypted) //打印重新解密的文本: fmt.Printf("\t解密后: %s\n\n", decrypted)}// ^ 实现混合密码系统加密func hybridEncrypt(publicKey rsa.PublicKey, message string) string { AES_key := AES_Key_Generator() encrypted, err := AES_Encrypt(AES_key, message) CheckError(err) head := RSA_OAEP_Encrypt(publicKey, string(AES_key)) return base64.RawStdEncoding.EncodeToString([]byte(head + "|组合加密的会话密钥与消息|" + encrypted))}// ^ 实现混合密码系统解密func hybridDecrypt(privateKey *rsa.PrivateKey, message string) string { mes, err := base64.RawStdEncoding.DecodeString(message) CheckError(err) splits := strings.Split(string(mes), "|组合加密的会话密钥与消息|") head, encrypted := splits[0], splits[1] AES_key := RSA_OAEP_Decrypt(privateKey, head) decrypted, err := AES_Decrypt([]byte(AES_key), encrypted) CheckError(err) return decrypted}

经验总结扩展阅读