vlambda博客
学习文章列表

非对称加密,从理论到代码,再到应用

关于非对称加密的原理和应用--
非对称加密容易误解的一个点--公钥和私钥到底哪个才是用来加密和哪个用来解密[3]

其中一个高赞回答:
不要去硬记。
你只要想:既然是加密,那肯定是不希望别人知道我的消息,所以只有我才能解密,所以可得出公钥负责加密,私钥负责解密;
同理,既然是签名,那肯定是不希望有人冒充我发消息,只有我才能发布这个签名,所以可得出私钥负责签名,公钥负责验证。

非对称加密的一个实现--RSA算法:
package rsa_algorithm

import (
 "bytes"
 "crypto/rand"
 "crypto/rsa"
 "crypto/x509"
 "encoding/pem"
 "errors"
)

func GenPair(bits int, passwd string) (priKey, pubKey []byte, err error) {
 // 生成私钥
 var privateKey *rsa.PrivateKey
 if privateKey, err = rsa.GenerateKey(rand.Reader, bits); err != nil {
  return
 }
 priStream := x509.MarshalPKCS1PrivateKey(privateKey)
 block := &pem.Block{Type: passwd, Bytes: priStream}
 priKey = pem.EncodeToMemory(block)
 // 生成公钥
 publicKey := &privateKey.PublicKey
 var pubStream []byte
 if pubStream, err = x509.MarshalPKIXPublicKey(publicKey); err != nil {
  return
 }
 block = &pem.Block{Type: passwd, Bytes: pubStream}
 pubKey = pem.EncodeToMemory(block)
 return
}

func Encrypt(pubKey, origData []byte) ([]byte, error) {
 block, _ := pem.Decode(pubKey)
 if block == nil {
  return nil, errors.New("public key error")
 }
 publicKey, err := x509.ParsePKIXPublicKey(block.Bytes)
 if err != nil {
  return nil, err
 }
 pub := publicKey.(*rsa.PublicKey)
 k := (pub.N.BitLen() + 7) / 8
 partLen := k - 11
 chunks := split(origData, partLen)
 buf := bytes.NewBuffer(make([]byte0, k))
 for _, chunk := range chunks {
  bytes, err := rsa.EncryptPKCS1v15(rand.Reader, pub, chunk)
  // fmt.Println("out chunk len:", len(bytes))
  if err != nil {
   return []byte{}, err
  }
  if _, err = buf.Write(bytes); err != nil {
   return []byte{}, err
  }
 }
 return buf.Bytes(), nil
}

func Decrypt(priKey, ciphertext []byte) ([]byte, error) {
 block, _ := pem.Decode(priKey)
 if block == nil {
  return nil, errors.New("private key error!")
 }
 privateKey, err := x509.ParsePKCS1PrivateKey(block.Bytes)
 if err != nil {
  return nil, err
 }
 partLen := (privateKey.N.BitLen() + 7) / 8
 chunks := split([]byte(ciphertext), partLen)
 buf := bytes.NewBuffer(make([]byte0, partLen))
 for _, chunk := range chunks {
  bytes, err := rsa.DecryptPKCS1v15(rand.Reader, privateKey, chunk)
  if err != nil {
   return []byte{}, err
  }
  if _, err = buf.Write(bytes); err != nil {
   return []byte{}, err
  }
 }
 return buf.Bytes(), nil
}

func split(buf []byte, lim int) [][]byte {
 var chunk []byte
 chunks := make([][]byte0len(buf)/lim+1)
 for len(buf) >= lim {
  chunk, buf = buf[:lim], buf[lim:]
  chunks = append(chunks, chunk)
 }
 if len(buf) > 0 {
  chunks = append(chunks, buf)
 }
 return chunks
}

参考资料

[1]

Markdown: http://www.youdzone.com/signature.html

[2]

Markdown: https://mp.weixin.qq.com/s?__biz=MjM5NTcxMTE2Nw%3D%3D&mid=2653115636&idx=1&sn=4573ede8a7dfdde52adef4ae281cf3ca&scene=45#wechat_redirect

[3]

Markdown: https://www.zhihu.com/question/25912483