encoding/pem

2018-12-25  本文已影响3人  酷走天涯

pem包实现了PEM数据编码(源自保密增强邮件协议)。目前PEM编码主要用于TLS密钥和证书

PEM 编码格式如下

-----BEGIN Type-----
Headers
base64-encoded Bytes
-----END Type-----

编码

func Encode(out io.Writer, b *Block) error

type Block struct {
    Type    string            // 得自前言的类型(如"RSA PRIVATE KEY")
    Headers map[string]string // 可选的头项
    Bytes   []byte            // 内容解码后的数据,一般是DER编码的ASN.1结构
}

下面我们就以ras加密方式为例,看一个pem编码的实现过程

package main

import (
    "crypto/rsa"
    "crypto/rand"
    "fmt"
    "encoding/pem"
    "crypto/x509"
    "os"
    "log"
    "io/ioutil"
    "errors"
)
var privite_key_path = "/Users/xujie/go/src/awesomeProject/main/private.pem"
var public_key_path = "/Users/xujie/go/src/awesomeProject/main/public.pem"

func main() {

  // 生成公钥和私钥
  generatePublick(generatePrivate())
  src := []byte(`{"name":"酷走天涯"}`)
  // 公钥加密
  cryptoData,error := rsaEncrypt(src)
  if error != nil {
      log.Fatal(error)
  }
  fmt.Println("加密:",cryptoData)

  // 私钥解密
  dst,error := rsaDecrypt(cryptoData)
    if error != nil {
        log.Fatal(error)
    }
    fmt.Println("解密:",string(dst))
}

// 生成私钥
func generatePrivate() *rsa.PrivateKey{
    
   
    privateKey,error :=  rsa.GenerateKey(rand.Reader,2048)
    if error != nil {
        fmt.Println(error)
    }
    derStream := x509.MarshalPKCS1PrivateKey(privateKey)
    block := &pem.Block{Type:"RSA PRIVATE KEY",Bytes:derStream}

    file,error := os.Create(privite_key_path)
    if error != nil {
        fmt.Println(error)
    }
    error = pem.Encode(file,block)
    if error != nil {
        fmt.Println(error)
    }
    return privateKey
}

// 生成公钥
func generatePublick(privateKey *rsa.PrivateKey){
    publicKey := privateKey.Public()
    derStream,error := x509.MarshalPKIXPublicKey(publicKey)
    if error != nil{
        fmt.Println(error)
    }
    block := &pem.Block{Type:"RSA PUBLIC KEY",Bytes:derStream}
    file,error := os.Create(public_key_path)
    if error != nil {
        fmt.Println(error)
    }
    error = pem.Encode(file,block)
    if error != nil {
        fmt.Println(error)
    }
}

// 公钥加密
func rsaEncrypt(origData []byte) ([]byte, error) {

   // 从文件中读取公钥编码字节流
   file,error := os.Open(public_key_path)
   if error != nil{
       log.Fatal(error)
   }


    publicKey,error := ioutil.ReadAll(file)
    if error != nil{
        log.Fatal(error)
    }
    // 解码对应的block块数据
    block, _ := pem.Decode(publicKey)
    if block == nil {
        return nil, errors.New("public key error")
    }

    // 获取公钥key值
    pubInterface, err := x509.ParsePKIXPublicKey(block.Bytes)
    if err != nil {
        return nil, err
    }
    pub := pubInterface.(*rsa.PublicKey)

    // 加密数据
    return rsa.EncryptPKCS1v15(rand.Reader, pub, origData)
}



// 私钥解密
func rsaDecrypt(ciphertext []byte) ([]byte, error) {

    // 从文件中读取私钥pem字节流
    file,error := os.Open(privite_key_path)
    if error != nil{
        log.Fatal(error)
    }
    privateKey,error := ioutil.ReadAll(file)
    if error != nil{
        log.Fatal(error)
    }
    // 解码出对应的block值
    block, _ := pem.Decode(privateKey)
    if block == nil {
        return nil, errors.New("private key error!")
    }

    // 获取私钥对象
    priv, err := x509.ParsePKCS1PrivateKey(block.Bytes)
    if err != nil {
        return nil, err
    }

    // 解密文件
    return rsa.DecryptPKCS1v15(rand.Reader, priv, ciphertext)
}

image.png

rsa.GenerateKey(rand.Reader,2048) 2048 是默认的的数据长度,也可以设置其他值

上一篇 下一篇

猜你喜欢

热点阅读