- 作者:老汪软件技巧
- 发表时间:2024-10-12 00:01
- 浏览量:
一、对称加密 对称加密是一种加密方式,其中加密和解密过程使用相同的密钥。在Go中,可以利用crypto/aes包来实现AES(高级加密标准)加密。以下是一个简单的示例:
package main
import (
"crypto/aes"
"crypto/cipher"
"fmt"
)
func main() {
key := []byte("this is a very secret key") // 密钥长度必须是16, 24或者32字节
plaintext := []byte("hello world")
block, err := aes.NewCipher(key)
if err != nil {
panic(err)
}
ciphertext := make([]byte, aes.BlockSize+len(plaintext))
iv := ciphertext[:aes.BlockSize]
if _, err := rand.Read(iv); err != nil {
panic(err)
}
stream := cipher.NewCFBEncrypter(block, iv)
stream.XORKeyStream(ciphertext[aes.BlockSize:], plaintext)
fmt.Printf("%x\n", ciphertext) // 输出加密后的文本
}
二、非对称加密 非对称加密采用一对密钥:公钥和私钥。公钥用于加密信息,而私钥则用于解密。RSA是一种广泛使用的非对称加密算法,在Go中可以通过crypto/rsa包来使用它。
package main
import (
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"encoding/pem"
"errors"
"fmt"
"os"
)
// 生成RSA密钥对
func generateKeyPair() (*rsa.PrivateKey, error) {
return rsa.GenerateKey(rand.Reader, 2048)
}
// 将私钥编码为PEM格式
func encodePrivateKeyToPEM(privateKey *rsa.PrivateKey) (string, error) {
privateKeyBytes := x509.MarshalPKCS1PrivateKey(privateKey)
pemBlock := &pem.Block{
Type: "RSA PRIVATE KEY",
Bytes: privateKeyBytes,
}
return pem.EncodeToMemory(pemBlock), nil
}
// 将公钥编码为PEM格式
func encodePublicKeyToPEM(publicKey *rsa.PublicKey) (string, error) {
publicKeyBytes, err := x509.MarshalPKIXPublicKey(publicKey)
if err != nil {
return "", err
}
pemBlock := &pem.Block{
Type: "PUBLIC KEY",
Bytes: publicKeyBytes,
}
return pem.EncodeToMemory(pemBlock), nil
}
// 使用公钥加密数据
func encryptWithPublicKey(plaintext []byte, publicKey *rsa.PublicKey) ([]byte, error) {
return rsa.EncryptOAEP(sha256.New(), rand.Reader, publicKey, plaintext, nil)
}
// 使用私钥解密数据
func decryptWithPrivateKey(ciphertext []byte, privateKey *rsa.PrivateKey) ([]byte, error) {
return rsa.DecryptOAEP(sha256.New(), rand.Reader, privateKey, ciphertext, nil)
}
func main() {
// 生成密钥对
privateKey, err := generateKeyPair()
if err != nil {
fmt.Fprintf(os.Stderr, "Failed to generate key pair: %v\n", err)
return
}
// 编码密钥为PEM格式
privPEM, err := encodePrivateKeyToPEM(privateKey)
if err != nil {
fmt.Fprintf(os.Stderr, "Failed to encode private key: %v\n", err)
return
}
pubPEM, err := encodePublicKeyToPEM(&privateKey.PublicKey)
if err != nil {
fmt.Fprintf(os.Stderr, "Failed to encode public key: %v\n", err)
return
}
// 显示PEM格式的密钥
fmt.Println("Private Key (PEM):")
fmt.Println(string(privPEM))
fmt.Println("Public Key (PEM):")
fmt.Println(string(pubPEM))
// 加密消息
message := []byte("Hello, RSA!")
encrypted, err := encryptWithPublicKey(message, &privateKey.PublicKey)
if err != nil {
fmt.Fprintf(os.Stderr, "Encryption failed: %v\n", err)
return
}
fmt.Printf("Encrypted: %x\n", encrypted)
// 解密消息
decrypted, err := decryptWithPrivateKey(encrypted, privateKey)
if err != nil {
fmt.Fprintf(os.Stderr, "Decryption failed: %v\n", err)
return
}
if string(decrypted) != string(message) {
errors.New("Decrypted data does not match the original message")
}
fmt.Printf("Decrypted: %s\n", decrypted)
}
三、哈希函数 哈希函数可以将任意长度的数据映射为固定长度的值,并且这个转换过程是不可逆的。常用的哈希函数如SHA-256可以在crypto/sha256包中找到。下面是如何计算一段文字的SHA-256哈希值的例子:
Go
import (
"crypto/sha256"
"fmt"
)
func main() {
text := "Secure message"
hash := sha256.Sum256([]byte(text))
fmt.Printf("%x\n", hash) // 输出哈希结果
}
四、数字签名 数字签名是一种用于验证消息完整性和来源的技术。在Go中,可以通过crypto/rsa包来创建和验证RSA数字签名。以下是一个简单的例子:
Go
深色版本
package main
import (
"crypto"
"crypto/rand"
"crypto/rsa"
"crypto/sha256"
"fmt"
)
func main() {
// 生成一对RSA密钥
privateKey, err := rsa.GenerateKey(rand.Reader, 2048)
if err != nil {
panic(err)
}
publicKey := &privateKey.PublicKey
message := []byte("Very important data")
hash := sha256.Sum256(message)
// 使用私钥对哈希值进行签名
signature, err := rsa.SignPKCS1v15(rand.Reader, privateKey, crypto.SHA256, hash[:])
if err != nil {
panic(err)
}
// 验证签名
err = rsa.VerifyPKCS1v15(publicKey, crypto.SHA256, hash[:], signature)
if err != nil {
fmt.Println("Signature verification failed.")
} else {
fmt.Println("Signature is valid.")
}
}
五、安全的随机数生成 对于任何加密操作而言,高质量的随机性都是至关重要的。Go提供了crypto/rand包,它基于操作系统提供的加密级随机源。例如,生成一个随机字节序列可以这样实现:
Go
深色版本
package main
import (
"crypto/rand"
"fmt"
)
func main() {
randomBytes := make([]byte, 32) // 生成32个字节的随机数据
_, err := rand.Read(randomBytes)
if err != nil {
panic(err)
}
fmt.Printf("%x\n", randomBytes)
}
六、密码散列与加盐 直接存储用户密码是不安全的做法。通常我们会使用单向散列函数(如bcrypt)结合“盐”来处理密码。/x/crypto/bcrypt库提供了一个方便的方式来执行这一过程:
Go
深色版本
package main
import (
"golang.org/x/crypto/bcrypt"
"fmt"
)
func main() {
password := []byte("password123")
// 生成带盐的哈希值
hashedPassword, err := bcrypt.GenerateFromPassword(password, bcrypt.DefaultCost)
if err != nil {
panic(err)
}
fmt.Println(string(hashedPassword))
// 检查密码是否匹配
err = bcrypt.CompareHashAndPassword(hashedPassword, password)
if err == nil {
fmt.Println("Password matches!")
} else {
fmt.Println("Incorrect password.")
}
}