- cipher
- aes
- des
- md5
- sha256
- dsa
- ecdsa
- elliptic
- hmac
- rand
- rc4
- rsa
aes
高级加密标准(英语:Advanced Encryption Standard,缩写:AES),对称加密
如美国联邦信息处理标准出版物197中所定义的,aes实现 AES 加密(以前称为 Rijndael)。 这个包中的 AES 操作不是使用恒定时间算法实现的。在支持 AES 的硬件支持的系统上运行时会有一个例外,这些操作会使这些操作保持恒定时间。例子包括使用 AES-NI 扩展的 amd64 系统和使用 Message-Security-Assist 扩展的 s390x 系统。在这样的系统中,当 NewCipher 的结果传递给 cipher.NewGCM 时,GCM 使用的 GHASH 操作也是恒定的
我们来演示一下加密解密过程
代码语言:javascript复制package main
import (
"bytes"
"crypto/aes"
"crypto/cipher"
"encoding/base64"
"fmt"
)
func main() {
testAes()
}
func testAes() {
// AES-128。key长度:16, 24, 32 bytes 对应 AES-128, AES-192, AES-256
key := []byte("1234560123456789")
result, err := AesEncrypt([]byte("123"), key)
if err != nil {
panic(err)
}
fmt.Println(base64.StdEncoding.EncodeToString(result))
origData, err := AesDecrypt(result, key)
if err != nil {
panic(err)
}
fmt.Println(string(origData))
}
// 加密
func AesEncrypt(origData, key []byte) ([]byte, error) {
// 1.创建密文变量
block, err := aes.NewCipher(key)
if err != nil {
return nil, err
}
// 2.获取块的大小
blockSize := block.BlockSize()
// 3.使用算法填充数据使其程度成为key的整数倍
origData = PKCS5Padding(origData, blockSize)
// origData = ZeroPadding(origData, block.BlockSize())
// 4.创建加密类型变量
blockMode := cipher.NewCBCEncrypter(block, key[:blockSize])
// 5.
crypted := make([]byte, len(origData))
// 根据CryptBlocks方法的说明,如下方式初始化crypted也可以
// crypted := origData
// 6.开始加密
blockMode.CryptBlocks(crypted, origData)
return crypted, nil
}
// 解密
func AesDecrypt(crypted, key []byte) ([]byte, error) {
// 1.创建密文变量
block, err := aes.NewCipher(key)
if err != nil {
return nil, err
}
// 2.获取加密块长度
blockSize := block.BlockSize()
//3.创建解密数据
blockMode := cipher.NewCBCDecrypter(block, key[:blockSize])
// 4.创建解密后存放数据的变量
origData := make([]byte, len(crypted))
// origData := crypted
// 5.解密数据
blockMode.CryptBlocks(origData, crypted)
// 6.去掉填充
origData = PKCS5UnPadding(origData)
// origData = ZeroUnPadding(origData)
return origData, nil
}
func ZeroPadding(ciphertext []byte, blockSize int) []byte {
padding := blockSize - len(ciphertext)%blockSize
padtext := bytes.Repeat([]byte{0}, padding)
return append(ciphertext, padtext...)
}
func ZeroUnPadding(origData []byte) []byte {
length := len(origData)
unpadding := int(origData[length-1])
return origData[:(length - unpadding)]
}
func PKCS5Padding(ciphertext []byte, blockSize int) []byte {
padding := blockSize - len(ciphertext)%blockSize
padtext := bytes.Repeat([]byte{byte(padding)}, padding)
return append(ciphertext, padtext...)
}
func PKCS5UnPadding(origData []byte) []byte {
length := len(origData)
// 去掉最后一个字节 unpadding 次
unpadding := int(origData[length-1])
return origData[:(length - unpadding)]
}
image.png
上面演示把‘123’通过一个秘钥key加密和解密的过程1234560123456789
des
DES算法的入口参数有三个:Key、Data、Mode。其中Key为7个字节共56位,是DES算法的工作密钥;Data为8个字节64位,是要被加密或被解密的数据;Mode为DES的工作方式,有两种:加密或解密
代码语言:javascript复制package main
import (
"bytes"
"crypto/cipher" //cipher密码
"crypto/des"
"encoding/base64" //将对象转换成字符串
"fmt"
)
/**
* DES加密方法
*/
func MyDesEncrypt(orig, key string) string{
// 1.将加密内容和秘钥转成字节数组
origData := []byte(orig)
k := []byte(key)
// 2.创建一个加密器
block, _ := des.NewCipher(k)
//3.将明文按秘钥的长度做补全操作
origData = PKCS5Padding(origData, block.BlockSize())
//4.返回一个解密接口-CBC
blockMode := cipher.NewCBCEncrypter(block, k)
//5.创建明文长度的字节数组
crypted := make([]byte, len(origData))
// 6.加密明文
blockMode.CryptBlocks(crypted, origData)
//将字节数组转换成字符串,base64编码
return base64.StdEncoding.EncodeToString(crypted)
}
/**
* DES解密方法
*/
func MyDESDecrypt(data string, key string) string {
k := []byte(key)
//将加密字符串用base64转换成字节数组
crypted, _ := base64.StdEncoding.DecodeString(data)
//将字节秘钥转换成block快
block, _ := des.NewCipher(k)
//设置解密方式-CBC
blockMode := cipher.NewCBCDecrypter(block, k)
//创建密文大小的数组变量
origData := make([]byte, len(crypted))
//解密密文到数组origData中
blockMode.CryptBlocks(origData, crypted)
//去掉加密时补全的部分
origData = PKCS5UnPadding(origData)
return string(origData)
}
/**
* 实现明文的补全
* 如果ciphertext的长度为blockSize的整数倍,则不需要补全
* 否则差几个则被几个,例:差5个则补5个5
*/
func PKCS5Padding(ciphertext []byte, blockSize int) []byte {
padding := blockSize - len(ciphertext)%blockSize
padtext := bytes.Repeat([]byte{byte(padding)}, padding)
return append(ciphertext, padtext...)
}
/**
* 实现去补码,PKCS5Padding的反函数
*/
func PKCS5UnPadding(origData []byte) []byte {
length := len(origData)
// 去掉最后一个字节 unpadding 次
unpadding := int(origData[length-1])
return origData[:(length - unpadding)]
}
func main() {
orig := "Hello World!"
fmt.Println("原文:", orig)
//声明秘钥,利用此秘钥实现明文的加密和密文的解密,长度必须为8
key := "12345678"
//加密
encyptCode := MyDesEncrypt(orig, key)
fmt.Println("密文:", encyptCode)
//解密
decyptCode := MyDESDecrypt(encyptCode, key)
fmt.Println("解密结果:", decyptCode)
}
md5
image.png
代码语言:javascript复制package main
import (
"crypto/md5"
"fmt"
"encoding/base64"
)
func main() {
s:= []byte("123456789")
result := md5.Sum(s)
fmt.Println(base64.StdEncoding.EncodeToString(result[:]))
}
image.png
sha256
代码语言:javascript复制package main
import (
"fmt"
"encoding/base64"
"crypto/sha256"
)
func main() {
s:= []byte("123456789")
result := sha256.Sum256(s)
fmt.Println(base64.StdEncoding.EncodeToString(result[:]))
}
image.png
rsa
下面我们看一下dsa的签名过程
代码语言:javascript复制package main
import (
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"encoding/pem"
"os"
)
func main() {
//rsa 密钥文件产生
GenRsaKey(1024)
}
//RSA公钥私钥产生
func GenRsaKey(bits int) error {
// 生成私钥文件
privateKey, err := rsa.GenerateKey(rand.Reader, bits)
if err != nil {
return err
}
derStream := x509.MarshalPKCS1PrivateKey(privateKey)
// 构造pem 结构
block := &pem.Block{
Type: "RSA PRIVATE KEY",
Bytes: derStream,
}
file, err := os.Create("private.pem")
if err != nil {
return err
}
// 将block 结构块 写入文件中
err = pem.Encode(file, block)
if err != nil {
return err
}
// 生成公钥文件
publicKey := &privateKey.PublicKey
// 将公钥转换为 DER-encoded PKIX 格式
derPkix, err := x509.MarshalPKIXPublicKey(publicKey)
if err != nil {
return err
}
// 生成证书格式
block = &pem.Block{
Type: "PUBLIC KEY",
Bytes: derPkix,
}
file, err = os.Create("public.pem")
if err != nil {
return err
}
// 生成证书文件
err = pem.Encode(file, block)
if err != nil {
return err
}
return nil
}
hmac
hmac包实现了U.S. Federal Information Processing Standards Publication 198规定的HMAC(加密哈希信息认证码)。
HMAC是使用key标记信息的加密hash。接收者使用相同的key逆运算来认证hash。
hmac主要应用在身份验证中,它的使用方法是这样的: (1) 客户端发出登录请求(假设是浏览器的GET请求) (2) 服务器返回一个随机值,并在会话中记录这个随机值 (3) 客户端将该随机值作为密钥,用户密码进行hmac运算,然后提交给服务器 (4) 服务器读取用户数据库中的用户密码和步骤2中发送的随机值做与客户端一样的hmac运算,然后与用户发送的结果比较,如果结果一致则验证用户合法
代码语言:javascript复制package main
import (
"crypto/hmac"
"crypto/sha256"
"encoding/json"
"fmt"
"encoding/base64"
)
const key = "asdfasdfasdfasdf"
func main() {
// 1.服务端发送一个token 给客户端
serverSendKeyToClient(key)
}
func serverSendKeyToClient(key string){
// 2.服务器将数据进行hmac 运算,
keyHash := hmac.New(sha256.New,[]byte(key))
data := map[string]string{"username":"xujie"}
s,_:= json.Marshal(data)
keyHash.Write([]byte(string(s)))
expectedMAC := keyHash.Sum(nil)
fmt.Println("客户端计算的hmac:")
fmt.Println(base64.StdEncoding.EncodeToString(expectedMAC))
// 3.将运算后的hash 值和数据发送给服务端 服务器
clientSendMessageToServer(string(s),string(expectedMAC))
}
func clientSendMessageToServer(message,messageMac string){
// 服务端接受数据后进行hmac 运算 如果结果和客户端传递过来的一致 就表示数据没有被篡改
fmt.Println(CheckMAC([]byte(message),[]byte(messageMac),[]byte(key)))
data := map[string]string{}
json.Unmarshal([]byte(message),data)
fmt.Println(message)
}
// 如果messageMAC是message的合法HMAC标签,函数返回真
func CheckMAC(message, messageMAC, key []byte) bool {
mac := hmac.New(sha256.New, key)
mac.Write(message)
expectedMAC := mac.Sum(nil)
fmt.Println("服务器计算的hmac:")
fmt.Println(base64.StdEncoding.EncodeToString(expectedMAC))
return hmac.Equal(messageMAC, expectedMAC)
}
image.png
rand
- func Read(b []byte) (n int, err error)
package main
import (
"fmt"
"crypto/rand"
"bytes"
)
func main() {
c := 10
b := make([]byte, c)
// 生成随机数填满切片b
_, err := rand.Read(b)
if err != nil {
fmt.Println("error:", err)
return
}
fmt.Println(b)
// 切片现在应该包含随机字节而不是仅包含零。
fmt.Println(bytes.Equal(b, make([]byte, c)))
}