非对称加密,从理论到代码,再到应用
关于非对称加密的原理和应用--
非对称加密容易误解的一个点--公钥和私钥到底哪个才是用来加密和哪个用来解密[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([]byte, 0, 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([]byte, 0, 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([][]byte, 0, len(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
}
参考资料
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