匠心精神 - 良心品质腾讯认可的专业机构-IT人的高薪实战学院

咨询电话:4000806560

Golang中的加密和解密:使用AES和RSA算法

Golang中的加密和解密:使用AES和RSA算法

随着互联网的不断发展,安全性越来越受到人们的关注。加密和解密成为了保护数据安全的重要手段之一。在Golang中,加密和解密可以使用AES和RSA算法来实现。本文将介绍Golang中如何使用AES和RSA算法进行加密和解密。

一、AES

AES是一种高级加密标准,是一种对称加密算法。对称加密算法是指加密和解密所使用的密钥是相同的。使用AES算法进行加密和解密需要先生成一个密钥,然后使用该密钥进行加密和解密操作。

1.生成密钥

生成密钥可以使用crypto/rand包中的函数实现。下面是一个生成32位密钥的示例代码:

```go
key := make([]byte, 32)
if _, err := rand.Read(key); err != nil {
    log.Fatal(err)
}
```

2.加密

使用AES算法进行加密需要使用crypto/aes包中的函数实现。下面是一个使用AES算法进行加密的示例代码:

```go
func aesEncrypt(plaintext []byte, key []byte) ([]byte, error) {
    block, err := aes.NewCipher(key)
    if err != nil {
        return nil, err
    }
    plaintext = PKCS5Padding(plaintext, block.BlockSize())
    ciphertext := make([]byte, len(plaintext))
    iv := make([]byte, aes.BlockSize)
    if _, err := rand.Read(iv); err != nil {
        return nil, err
    }
    mode := cipher.NewCBCEncrypter(block, iv)
    mode.CryptBlocks(ciphertext, plaintext)
    ciphertext = append(iv, ciphertext...)
    return ciphertext, nil
}
```

在上面的代码中,使用AES算法进行加密的关键步骤是:

1.创建AES加密器,使用密钥key作为参数。

2.对明文进行填充,使其长度为AES块大小的倍数。

3.生成一个随机的初始化向量iv。

4.创建CBC加密模式,使用加密器和初始化向量iv作为参数。

5.对明文进行加密,返回密文。

在加密过程中,需要注意的是,需要使用填充算法对明文进行填充,以保证明文长度是AES块大小的倍数。

3.解密

使用AES算法进行解密的过程与加密过程类似。下面是一个使用AES算法进行解密的示例代码:

```go
func aesDecrypt(ciphertext []byte, key []byte) ([]byte, error) {
    block, err := aes.NewCipher(key)
    if err != nil {
        return nil, err
    }
    iv := ciphertext[:aes.BlockSize]
    ciphertext = ciphertext[aes.BlockSize:]
    mode := cipher.NewCBCDecrypter(block, iv)
    plaintext := make([]byte, len(ciphertext))
    mode.CryptBlocks(plaintext, ciphertext)
    plaintext = PKCS5UnPadding(plaintext)
    return plaintext, nil
}
```

在上面的代码中,使用AES算法进行解密的关键步骤是:

1.创建AES解密器,使用密钥key作为参数。

2.从密文中获取初始化向量iv。

3.创建CBC解密模式,使用解密器和初始化向量iv作为参数。

4.对密文进行解密,返回明文。

在解密过程中,需要注意的是,需要使用填充算法对解密出来的明文进行去填充,以得到原始的明文。

二、RSA

RSA是一种非对称加密算法。与对称加密算法不同,RSA算法加密和解密使用的密钥是不同的。RSA算法包括公钥和私钥两个密钥,公钥用于加密,私钥用于解密。

1.生成密钥对

生成RSA密钥对可以使用crypto/rsa包中的函数实现。下面是一个生成RSA密钥对的示例代码:

```go
func generateRSAKey() (*rsa.PrivateKey, error) {
    bits := 2048
    privateKey, err := rsa.GenerateKey(rand.Reader, bits)
    if err != nil {
        return nil, err
    }
    return privateKey, nil
}
```

在上面的代码中,使用2048位的RSA算法生成一个私钥。

2.加密

使用RSA算法进行加密需要使用crypto/rsa包中的函数实现。下面是一个使用RSA算法进行加密的示例代码:

```go
func rsaEncrypt(plaintext []byte, publicKey *rsa.PublicKey) ([]byte, error) {
    ciphertext, err := rsa.EncryptPKCS1v15(rand.Reader, publicKey, plaintext)
    if err != nil {
        return nil, err
    }
    return ciphertext, nil
}
```

在上面的代码中,使用RSA算法进行加密的关键步骤是:

1.调用rsa.EncryptPKCS1v15函数进行加密,使用公钥publicKey作为参数。

2.对密文进行返回。

3.解密

使用RSA算法进行解密的过程与加密过程类似。下面是一个使用RSA算法进行解密的示例代码:

```go
func rsaDecrypt(ciphertext []byte, privateKey *rsa.PrivateKey) ([]byte, error) {
    plaintext, err := rsa.DecryptPKCS1v15(rand.Reader, privateKey, ciphertext)
    if err != nil {
        return nil, err
    }
    return plaintext, nil
}
```

在上面的代码中,使用RSA算法进行解密的关键步骤是:

1.调用rsa.DecryptPKCS1v15函数进行解密,使用私钥privateKey作为参数。

2.对明文进行返回。

三、示例代码

下面是一个使用AES和RSA算法进行加密和解密的示例代码:

```go
package main

import (
    "crypto/aes"
    "crypto/cipher"
    "crypto/rand"
    "crypto/rsa"
    "crypto/sha256"
    "crypto/x509"
    "encoding/base64"
    "encoding/pem"
    "fmt"
    "io/ioutil"
    "log"
)

func main() {
    plaintext := "Hello, world!"
    fmt.Println("Plaintext:", plaintext)

    // AES加密
    key := make([]byte, 32)
    if _, err := rand.Read(key); err != nil {
        log.Fatal(err)
    }
    ciphertext, err := aesEncrypt([]byte(plaintext), key)
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println("AES key:", base64.StdEncoding.EncodeToString(key))
    fmt.Println("AES ciphertext:", base64.StdEncoding.EncodeToString(ciphertext))

    // RSA加密
    publicKey, err := readRSAPublicKey("public.pem")
    if err != nil {
        log.Fatal(err)
    }
    encryptedKey, err := rsaEncrypt(key, publicKey)
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println("RSA encrypted key:", base64.StdEncoding.EncodeToString(encryptedKey))

    // RSA解密
    privateKey, err := readRSAPrivateKey("private.pem")
    if err != nil {
        log.Fatal(err)
    }
    decryptedKey, err := rsaDecrypt(encryptedKey, privateKey)
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println("RSA decrypted key:", base64.StdEncoding.EncodeToString(decryptedKey))

    // AES解密
    plaintext2, err := aesDecrypt(ciphertext, decryptedKey)
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println("Plaintext2:", string(plaintext2))
}

func aesEncrypt(plaintext []byte, key []byte) ([]byte, error) {
    block, err := aes.NewCipher(key)
    if err != nil {
        return nil, err
    }
    plaintext = PKCS5Padding(plaintext, block.BlockSize())
    ciphertext := make([]byte, len(plaintext))
    iv := make([]byte, aes.BlockSize)
    if _, err := rand.Read(iv); err != nil {
        return nil, err
    }
    mode := cipher.NewCBCEncrypter(block, iv)
    mode.CryptBlocks(ciphertext, plaintext)
    ciphertext = append(iv, ciphertext...)
    return ciphertext, nil
}

func aesDecrypt(ciphertext []byte, key []byte) ([]byte, error) {
    block, err := aes.NewCipher(key)
    if err != nil {
        return nil, err
    }
    iv := ciphertext[:aes.BlockSize]
    ciphertext = ciphertext[aes.BlockSize:]
    mode := cipher.NewCBCDecrypter(block, iv)
    plaintext := make([]byte, len(ciphertext))
    mode.CryptBlocks(plaintext, ciphertext)
    plaintext = PKCS5UnPadding(plaintext)
    return plaintext, nil
}

func PKCS5Padding(src []byte, blockSize int) []byte {
    padding := blockSize - len(src)%blockSize
    padtext := bytes.Repeat([]byte{byte(padding)}, padding)
    return append(src, padtext...)
}

func PKCS5UnPadding(src []byte) []byte {
    length := len(src)
    unpadding := int(src[length-1])
    return src[:(length - unpadding)]
}

func readRSAPrivateKey(filename string) (*rsa.PrivateKey, error) {
    privateKeyBytes, err := ioutil.ReadFile(filename)
    if err != nil {
        return nil, err
    }
    privateKeyBlock, _ := pem.Decode(privateKeyBytes)
    privateKey, err := x509.ParsePKCS1PrivateKey(privateKeyBlock.Bytes)
    if err != nil {
        return nil, err
    }
    return privateKey, nil
}

func readRSAPublicKey(filename string) (*rsa.PublicKey, error) {
    publicKeyBytes, err := ioutil.ReadFile(filename)
    if err != nil {
        return nil, err
    }
    publicKeyBlock, _ := pem.Decode(publicKeyBytes)
    publicKey, err := x509.ParsePKCS1PublicKey(publicKeyBlock.Bytes)
    if err != nil {
        return nil, err
    }
    return publicKey, nil
}
```

在上面的代码中,首先使用AES算法对明文进行加密,然后使用RSA算法对密钥进行加密,最后把加密后的密钥和密文一起传输到对方。对方先使用RSA算法对密钥进行解密,然后再使用AES算法对密文进行解密,从而得到原始的明文。