切换语言为:繁体

盘点 Go 语言中的六种加密技术

  • 爱糖宝
  • 2024-10-11
  • 2038
  • 0
  • 0

一、对称加密 对称加密是一种加密方式,其中加密和解密过程使用相同的密钥。在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)结合“盐”来处理密码。golang.org/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.")
    }
}

0条评论

您的电子邮件等信息不会被公开,以下所有项均必填

OK! You can skip this field.