区块链加/解密 二
非对称加密:Rsa/ECC
加/解密算法中涉及的库及常用公钥标准
pem: 实现了PEM数据编码;主要用于TLS密钥和证书
x509: x509包解析X.509编码的证书和密钥。
x509.MarshalPKCS1PrivateKey(PrivateKey) :将rsa私钥序列化为ASN.1 PKCS#1 DER编码。
x509.MarshalPKIXPublicKey(&PublicKey) :将公钥序列化为PKIX格式DER编码
x509.ParsePKIXPublicKey(block.Bytes) :解析一个DER编码的公钥。这些公钥一般在以"BEGIN PUBLIC KEY"出现的PEM块中
x509.ParsePKCS1PrivateKey(block.Bytes) :解析ASN.1 PKCS#1 DER编码的rsa私钥
rsa: 实现了PKCS#1规定的RSA加密算法。
rsa.GenerateKey 使用随机数据生成器random生成一对具有指定字位数的RSA密钥
rsa.EncryptPKCS1v15(rand.Reader, pubkey, src)
rsa.DecryptPKCS1v15(rand.Reader, pubkey, src)
PKCS#1:定义RSA公开密钥算法加密和签名机制,主要用于组织PKCS#7中所描述的数字签名和数字信封[22]。
PKCS#3:定义Diffie-Hellman密钥交换协议。
PKCS#6:描述了公钥证书的标准语法,主要描述X.509证书的扩展格式。
PKCS#7:定义一种通用的消息语法,包括数字签名和加密等用于增强的加密机制,PKCS#7与PEM兼容;
PKCS#13:椭圆曲线密码体制标准。
PKCS#15:密码令牌信息格式标准。
Rsa:生成公私钥文件
- 生成私钥操作流程
1.使用rsa中GenerateKey方法生成私钥
2.通过x509标准将得到的rsa私钥序列化为ASN.1的DER编码字符串
3.将私钥字符串设置到pem格式块中
4.通过pem将设置好的数据进行编码,并写入磁盘文件中 - 生成公钥操作流程
1.从得到的私钥对象中将公钥信息取出
2.通过x509标准将得到的rsa公钥序列化为ASN.1的DER编码字符串
3.将公钥字符串设置到pem格式块中
4.通过pem将设置好的数据进行编码,并写入磁盘文件中
//go语言算法实现
func GeneRsa(blockSize int) error {
PrivateKey, err := rsa.GenerateKey(rand.Reader, blockSize)
if err != nil {
return err
}
stream := x509.MarshalPKCS1PrivateKey(PrivateKey)
block := pem.Block{
Type: "RSA PrivateKey",
Bytes: stream,
}
PrivateFile, err := os.Create("PrivateKey.pem")
if err != nil {
return err
}
err = pem.Encode(PrivateFile, &block)
PublicKey := PrivateKey.PublicKey
stream1, err := x509.MarshalPKIXPublicKey(&PublicKey)
if err != nil {
return err
}
block1 := pem.Block{
Type: "RSA PublicKey",
Bytes: stream1,
}
PublicFile, err := os.Create("PublicKey.pem")
if err != nil {
return err
}
err = pem.Encode(PublicFile, &block1)
return err
}
Rsa:公钥加密/私钥解密
- 公钥加密
1.将公钥取出得到PEM编码的字符串
2.将得到的字符串进行pem解码
3.使用x509进行解析公钥
4.使用Rsa对公钥进行加密 - 私钥解密
1.将私钥取出得到PEM编码的字符串
2.将得到的字符串进行pem解码
3.使用x509进行解析私钥
4.对私钥使用rsa进行解密
//公钥加密
func EnRsaPublickey(src []byte, fileName string) ([]byte, error) {
msg := []byte(" ")
file, err := os.Open(fileName)
if err != nil {
return msg, err
}
info, err := file.Stat()
if err != nil {
return msg, err
}
fileSize := info.Size()
newPem := make([]byte, fileSize)
file.Read(newPem)
block, _ := pem.Decode(newPem)
pubkey1, _ := x509.ParsePKIXPublicKey(block.Bytes)
pubkey := pubkey1.(*rsa.PublicKey)
msg, err = rsa.EncryptPKCS1v15(rand.Reader, pubkey, src)
if err != nil {
return msg, err
}
return msg, err
}
//私钥解密
func DeRsaPrivtekey(src []byte, fileName string) ([]byte, error) {
msg := []byte(" ")
file, err := os.Open(fileName)
if err != nil {
return msg, err
}
info, err := file.Stat()
if err != nil {
return msg, err
}
fileSize := info.Size()
newPem := make([]byte, fileSize)
file.Read(newPem)
block, _ := pem.Decode(newPem)
pubkey, _ := x509.ParsePKCS1PrivateKey(block.Bytes)
//pubkey := pubkey1.(*rsa.PublicKey)
msg, err = rsa.DecryptPKCS1v15(rand.Reader, pubkey, src)
fmt.Println("msg", msg)
if err != nil {
return msg, err
}
return msg, err
}
ECC:私钥签名/公钥解密
前天在学习ECC椭圆曲线加密时,读取了大量博客,可是没有找到真正实现算法的逻辑代码。
我实现的方式比较简单,大家多尝试编写几次,就能实现自己的代码。我将罗列出所有显示步骤的代码,帮助大家浅显易懂
package main
import (
"crypto/ecdsa"
"crypto/md5"
"encoding/hex"
"fmt"
"math/big"
"strings"
"crypto/elliptic"
"crypto/rand"
)
//进行测试
func main() {
src := []byte(string("少壮不努力,活该你单身23333"))
//这里是我实验,使用不同消息hash摘要进行验证,不用就好
//src1 := []byte(string("少壮不努力,老大徒伤悲3344"))
mysrc := myHash(src)
//mysrc1 := myHash(src1)
prk, puk, _ := genePriPubKey()
mystring := sign(prk, mysrc)
r, s := getSign(mystring)
result := verifySign(&r, &s, mysrc, puk)
fmt.Print(result)
}
//生成公/私钥
func genePriPubKey() (*ecdsa.PrivateKey, ecdsa.PublicKey, error) {
var err error
var pubkey ecdsa.PublicKey
var prikey *ecdsa.PrivateKey
var curve elliptic.Curve
curve = elliptic.P384()//使用的是P384椭圆曲线,可以尝试其他曲线,结果一样
prikey, err = ecdsa.GenerateKey(curve, rand.Reader)
if err != nil {
return prikey, pubkey, err
}
pubkey = prikey.PublicKey
return prikey, pubkey, err
}
//将消息进行hash摘要;我这里使用的是md5,大家也可以尝试其他hash算法
func myHash(src []byte) []byte {
myhash := md5.New()
myhash.Write(src)
return myhash.Sum(nil)
}
//使用私钥,hash摘要进行签名
func sign(key *ecdsa.PrivateKey, myhash []byte) string {
r, s, _ := ecdsa.Sign(rand.Reader, key, myhash)//返回一对大整数
rm, _ := r.MarshalText()//需要将大整数r,s转换成[]byte,才能被string
sm, _ := s.MarshalText()
return hex.EncodeToString([]byte(string(rm) + "+" + string(sm)))//编译成hex
}
//获取签名之后的密文,进行解密
func getSign(hexrs string) (rint, sint big.Int) {
st, _ := hex.DecodeString(hexrs)
str := strings.Split(string(st), "+")//解码之后的st,由r,s2部分拼接,需要对其拆分,然后逐一解码成大整数
_ = rint.UnmarshalText([]byte(str[0]))
//假如rint是指针:error: invalid memory address or nil pointer dereference
_ = sint.UnmarshalText([]byte(str[1]))
return
}
//对解密之后的明文,hash,公钥验证
func verifySign(rint, sint *big.Int, myhash []byte, pubkey ecdsa.PublicKey) bool {
//使用ecdsa.Verify进行验证即可
result := ecdsa.Verify(&pubkey, myhash, rint, sint)
return result
}