crypto 包
crypto 包包含了通用加密算法的集合,提供了一些加密过程中基本对象的封装或基本接口的定义.导入方式为 import "crypto"
.
当前我们项目中常用的加解密的方式无非三种.
对称加密: 加解密都使用的是同一个密钥,其中的代表就是 AES,DES(已被攻破)
非对加解密: 加解密使用不同的密钥,其中的代表就是 RSA
签名算法: 主要用于验证,防止信息被修改,多用于文件校验,数字签名,鉴权协议的等,其中算法主要有 MD5,SHA1,HMAC 等
类型定义 它主要包含如下加密过程中的基本类型定义
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 type Decrypter interface { Public() PublicKey Decrypt(rand io.Reader, msg []byte , opts DecrypterOpts) (plaintext []byte , err error) } type DecrypterOpts interface {}type Hash uint type PrivateKey interface {}type PublicKey interface {}type Signer interface { Public() PublicKey Sign(rand io.Reader, digest []byte , opts SignerOpts) (signature []byte , err error) } type SignerOpts interface { HashFunc() Hash }
常量及变量 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 const ( MD4 Hash = 1 + iota MD5 SHA1 SHA224 SHA256 SHA384 SHA512 MD5SHA1 RIPEMD160 SHA3_224 SHA3_256 SHA3_384 SHA3_512 SHA512_224 SHA512_256 BLAKE2s_256 BLAKE2b_256 BLAKE2b_384 BLAKE2b_512 )
子包 它包含众多子包,如下
名称
简介
aes
实现了 AES加密
cipher
实现了标准分组密码模式(CBC,ECB 等),可以将其包装在低级分组密码实现中
des
实现了数据加密标准(DES)和三重数据加密算法(TDEA)
dsa
实现了 FIPS 186-3 中定义的数字签名算法
ecdsa
实现了 FIPS 186-3 中定义的椭圆曲线数字签名算法
ed25519
实现了 ED25519签名算法
elliptic
实现了在素数域上的几个标准椭圆曲线
hmac
实现了 Keyed-Hash 消息认证码
md5
实现了 RFC 1321 中定义的 MD5 哈希算法
rand
实现了加密安全的随机数生成器
rc4
实现了 RC4 加密
rsa
实现了 PKCS#1 中定义的 RSA 加密
sha1
实现了 RFC 3174 中定义的 SHA-1 哈希算法
sha256
实现了 FIPS 180-4 中定义的 SHA224 和 SHA256 哈希算法
sha512
实现了 FIPS 180-4 中定义的 SHA-384, SHA-512, SHA-512/224 和 SHA-512/256 哈希算法
tls
部分实现了 RFC 5246 中指定的 TLS 1.2 和 RFC 8446 中指定的 TLS 1.3
x509
解析 X.509 编码的密钥和证书
x509/pkix
包含用于X.509证书,CRL 和 OCSP 的 ASN.1 解析和序列化的共享低级结构
crypto/aes
aes 包实现了 AES 对称加密.导入方式为 import "crypto/aes"
常用常量及变量
常用方法 1 2 3 func NewCipher (key []byte ) (cipher.Block, error)
crypto/cipher
cipher 包实现标准的分组加密模式(CBC,ECB 等),可以将其包装在低级分组加密实现中.导入方式为 import "crypto/cipher"
常用类型定义 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 type AEAD interface { NonceSize() int Overhead() int Seal(dst, nonce, plaintext, additionalData []byte ) []byte Open(dst, nonce, ciphertext, additionalData []byte ) ([]byte , error) } type Block interface { BlockSize() int Encrypt(dst, src []byte ) Decrypt(dst, src []byte ) } type BlockMode interface { BlockSize() int CryptBlocks(dst, src []byte ) } type Stream interface { XORKeyStream(dst, src []byte ) } type StreamReader struct { S Stream R io.Reader } type StreamWriter struct { S Stream W io.Writer Err error }
常用方法 cipher
包方法1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 func NewGCM (cipher Block) (AEAD, error) func NewGCMWithNonceSize (cipher Block, size int ) (AEAD, error) func NewCBCDecrypter (b Block, iv []byte ) BlockMode func NewCBCEncrypter (b Block, iv []byte ) BlockMode func NewCFBDecrypter (block Block, iv []byte ) Stream func NewCFBEncrypter (block Block, iv []byte ) Stream func NewCTR (block Block, iv []byte ) Stream func NewOFB (b Block, iv []byte ) Stream
示例 AES GCM 模式认证加密解密 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 import ( "crypto/aes" "crypto/cipher" "crypto/rand" "encoding/base64" "fmt" "io" ) func AESGCMEncrypt (plaintextStr string , keyStr string ) (string , string ) { plaintext := []byte (plaintextStr) key := []byte (keyStr) block, err := aes.NewCipher(key) if err != nil { panic (fmt.Sprintf("key 长度必须 16/24/32长度: %s" , err.Error())) } aesgcm, err := cipher.NewGCM(block) if err != nil { panic (err.Error()) } nonce := make ([]byte , aesgcm.NonceSize()) if _, err := io.ReadFull(rand.Reader, nonce); err != nil { panic (err.Error()) } ciphertext := aesgcm.Seal(nil , nonce, plaintext, nil ) fmt.Println(ciphertext, nonce, key) return base64.RawURLEncoding.EncodeToString(ciphertext), base64.RawURLEncoding.EncodeToString(nonce) } func AESGCMDecrypt (ciphertextStr string , keyStr string , nonceStr string ) string { ciphertext, _ := base64.RawURLEncoding.DecodeString(ciphertextStr) nonce, _ := base64.RawURLEncoding.DecodeString(nonceStr) key := []byte (keyStr) block, err := aes.NewCipher(key) if err != nil { panic (err.Error()) } aesgcm, err := cipher.NewGCM(block) if err != nil { panic (err.Error()) } plaintext, err := aesgcm.Open(nil , nonce, ciphertext, nil ) if err != nil { panic (err.Error()) } return string (plaintext) } func main () { plaintext := "hello world" key := "123456781234567812345678" fmt.Println("原文:" , plaintext) ciphertext, nonce := AESGCMEncrypt(plaintext, key) fmt.Println("密文: " , ciphertext, nonce) fmt.Println("解密结果: " , AESGCMDecrypt(ciphertext, key, nonce)) }
AES CBC 模式加密解密 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 import ( "bytes" "crypto/aes" "crypto/cipher" "encoding/base64" "fmt" ) func AESCBCEncrypt (plaintextStr string , keyStr string ) string { plaintext := []byte (plaintextStr) key := []byte (keyStr) block, err := aes.NewCipher(key) if err != nil { panic (fmt.Sprintf("key 长度必须 16/24/32长度: %s" , err.Error())) } blockSize := block.BlockSize() plaintext = PKCS7Padding(plaintext, blockSize) blockMode := cipher.NewCBCEncrypter(block, key[:blockSize]) ciphertext := make ([]byte , len (plaintext)) blockMode.CryptBlocks(ciphertext, plaintext) return base64.RawURLEncoding.EncodeToString(ciphertext) } func AESCBCDecrypt (ciphertextStr string , key string ) string { ciphertext, _ := base64.RawURLEncoding.DecodeString(ciphertextStr) k := []byte (key) block, err := aes.NewCipher(k) if err != nil { panic (fmt.Sprintf("key 长度必须 16/24/32长度: %s" , err.Error())) } blockSize := block.BlockSize() blockMode := cipher.NewCBCDecrypter(block, k[:blockSize]) plaintext := make ([]byte , len (ciphertext)) blockMode.CryptBlocks(plaintext, ciphertext) plaintext = PKCS7UnPadding(plaintext) return string (plaintext) } func PKCS7Padding (plaintext []byte , blocksize int ) []byte { padding := blocksize - len (plaintext)%blocksize padtext := bytes.Repeat([]byte {byte (padding)}, padding) return append (plaintext, padtext...) } func PKCS7UnPadding (plaintext []byte ) []byte { length := len (plaintext) unpadding := int (plaintext[length-1 ]) return plaintext[:(length - unpadding)] } func main () { plaintext := "hello world" key := "123456781234567812345678" fmt.Println("原文: " , plaintext) ciphertext := AESCBCEncrypt(plaintext, key) fmt.Println("密文: " , ciphertext) plaintext2 := AESCBCDecrypt(ciphertext, key) fmt.Println("解密结果: " , plaintext2) }
CFB 模式加密用法与 CBC 加密模式用法基本一致,在创建 blockMode
时调用对应的方法即可
crypto/md5
md5 包实现了 RFC 1321 中定义的 MD5 哈希算法.导入方式 import "crypto/md5"
. sha1
,sha256
,sha512
变量定义与相关方法与 md5
类似,不再赘述
常量及变量 1 2 3 4 const BlockSize = 64 const Size = 16
常用方法 1 2 3 4 func New () hash .Hash func Sum (data []byte ) [Size ]byte
示例 计算字符串的校验和 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 import ( "crypto/md5" "fmt" "io" ) func main () { h := md5.New() io.WriteString(h, "The fog is getting thicker!" ) io.WriteString(h, "And Leon's getting laaarger!" ) fmt.Printf("%x" , h.Sum(nil )) data := []byte ("These pretzels are making me thirsty." ) fmt.Printf("%x" , md5.Sum(data)) }
计算文件的校验和 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 import ( "crypto/md5" "fmt" "io" "log" "os" ) func main () { f, err := os.Open("file.txt" ) if err != nil { log.Fatal(err) } defer f.Close() h := md5.New() if _, err := io.Copy(h, f); err != nil { log.Fatal(err) } fmt.Printf("%x" , h.Sum(nil )) }
crypto/rand
rand 包实现了加密安全的随机数生成器.它在包中定义了全局唯一的 var Reader io.Reader
变量提供了以下方法用于生成随机数
常量及变量
函数 1 2 3 4 5 func Int (rand io.Reader, max *big.Int) (n *big.Int, err error) func Read (b []byte ) (n int , err error)
示例 1 2 3 4 5 nonce := make ([]byte , 12 ) if _, err := io.ReadFull(rand.Reader, nonce); err != nil { panic (err.Error()) }
crypto/rsa
rsa 实现了 RSA 非对称加密算法,该算法通过生成密钥对实现加密和加密,公钥文件用于加密,私钥用于解密.
RSA 是一个基本操作,在此程序包中用于实现公钥加密或公钥签名.此包中的 RSA 操作未使用固定时间算法实现.
常量及变量 1 2 3 4 5 6 const ( PSSSaltLengthAuto = 0 PSSSaltLengthEqualsHash = -1 )
类型定义 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 type PrivateKey struct { PublicKey D *big.Int Primes []*big.Int Precomputed PrecomputedValues } type PublicKey struct { N *big.Int E int } type OAEPOptions struct { Hash crypto.Hash Label []byte } type PKCS1v15DecryptOptions struct { SessionKeyLen int } type PSSOptions struct { SaltLength int Hash crypto.Hash }
常用方法 rsa
包函数1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 func GenerateKey (random io.Reader, bits int ) (*PrivateKey, error) func EncryptOAEP (hash hash.Hash, random io.Reader, pub *PublicKey, msg []byte , label []byte ) ([]byte , error) func DecryptOAEP (hash hash.Hash, random io.Reader, priv *PrivateKey, ciphertext []byte , label []byte ) ([]byte , error) func EncryptPKCS1v15 (rand io.Reader, pub *PublicKey, msg []byte ) ([]byte , error) func DecryptPKCS1v15 (rand io.Reader, priv *PrivateKey, ciphertext []byte ) ([]byte , error) func SignPKCS1v15 (rand io.Reader, priv *PrivateKey, hash crypto.Hash, hashed []byte ) ([]byte , error) func VerifyPKCS1v15 (pub *PublicKey, hash crypto.Hash, hashed []byte , sig []byte ) error func SignPSS (rand io.Reader, priv *PrivateKey, hash crypto.Hash, hashed []byte , opts *PSSOptions) ([]byte , error)
PrivateKey
结构体方法PrivateKey
结构体实现了 crypto.Decrypter
和 crypto.Signer
接口.具有以下方法
1 2 3 4 5 6 7 8 9 10 11 12 func (priv *PrivateKey) Decrypt (rand io.Reader, ciphertext []byte , opts crypto.DecrypterOpts) (plaintext []byte , err error) func (priv *PrivateKey) Precompute () func (priv *PrivateKey) Public () crypto .PublicKey func (priv *PrivateKey) Sign (rand io.Reader, digest []byte , opts crypto.SignerOpts) ([]byte , error) func (priv *PrivateKey) Validate () error
示例 对数据进行加密解密 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 import ( "crypto/rand" "crypto/rsa" "crypto/sha256" "fmt" "os" ) func main () { privateKey, err := rsa.GenerateKey(rand.Reader, 2048 ) if err != nil { fmt.Println(err) } msg := []byte ("send reinforcements, we're going to advance" ) label := []byte ("orders" ) rng := rand.Reader ciphertext, err := rsa.EncryptOAEP(sha256.New(), rng, &privateKey.PublicKey, msg, label) if err != nil { fmt.Fprintf(os.Stderr, "Error from encryption: %s\n" , err) return } fmt.Printf("Ciphertext: %x\n" , ciphertext) plaintext, err := rsa.DecryptOAEP(sha256.New(), rng, privateKey, ciphertext, label) if err != nil { fmt.Fprintf(os.Stderr, "Error from deecryption: %s\n" , err) return } fmt.Printf("Plaintext: %s\n" , string (plaintext)) }
对数据进行签名认证 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 import ( "crypto" "crypto/rand" "crypto/rsa" "crypto/sha256" "fmt" "os" ) func main () { privateKey, err := rsa.GenerateKey(rand.Reader, 2048 ) if err != nil { fmt.Println(err) } message := []byte ("message to be signed" ) hashed := sha256.Sum256(message) signature, err := rsa.SignPKCS1v15(rand.Reader, privateKey, crypto.SHA256, hashed[:]) if err != nil { fmt.Fprintf(os.Stderr, "Error from signing: %s\n" , err) return } fmt.Printf("Signature: %x\n" , signature) err = rsa.VerifyPKCS1v15(&privateKey.PublicKey, crypto.SHA256, hashed[:], signature) if err != nil { fmt.Fprintf(os.Stderr, "Error from verification: %s\n" , err) return } fmt.Println("认证通过" ) }