资讯详情

RSA 加密解密签名验签

api

package v1  // get请求 import "github.com/gogf/gf/v2/frame/g"  type GetKeyReq struct {  g.Meta `path:"/get_key" method:"get" summary:"获取公钥" tags:"RSA"`  Name   string `json:"name" v:"required#账号"   dc:"账号"` } type GetKeyRes struct {  //g.Meta `mime:"text/html" type:"string" example:"<html/>"`  Result string `json:"result" dc:"返回公钥"`  Public string `json:"public"  dc:"公钥"` }  type GetKeyPriReq struct {  g.Meta `path:"/get_key_pri" method:"get" summary:"获取公钥" tags:"RSA"` } type GetKeyPriRes struct {  //g.Meta `mime:"text/html" type:"string" example:"<html/>"`  Result  string `json:"result" dc:"返回公钥"`  Public  string `json:"public"  dc:"公钥"`  Private string `json:"private"  dc:"公钥"` }  type PostPublicKeyReq struct {  g.Meta `path:"/push_key" method:"post" summary:"用户上传公钥" tags:"RSA"`  Public string `json:"public" v:"required#公钥"   dc:"公钥"`  Name   string `json:"name" v:"required#账号"   dc:"账号"` } type PostPublicKeyRes struct {  Result string `json:"result" dc:"结果"` }  type VerifyReq struct {  g.Meta `path:"/verify" method:"post" summary:"验签" tags:"RSA"`  Sign   string `json:"sign" v:"required#签名"   dc:"签名"`  Name   string `json:"name" v:"required#账号"   dc:"账号"`  Data   string `json:"data" v:"required#签署信息"   dc:"签署信息"` } type VerifyRes struct {  Result bool `json:"result" dc:"验签结果"` } type DecryptReq struct {  g.Meta    `path:"/decrypt" method:"post" summary:"解密" tags:"RSA"`  Secret    string `json:"secret" v:"required#密文"   dc:"密文"`  Name      string `json:"name" v:"required#账号"   dc:"账号"`  PublicKey string `json:"publickey" v:"required#公钥"   dc:"公钥"` } type DecryptRes struct {  Result string `json:"result" dc:"解密结果"` }  

controller

package controller  import (  "context"  "crypto"  v1 "firstproject/api/v1"  "firstproject/internal/service" )  var (  Rsa = cRsa{} )  type cRsa struct{}  // 获取公钥 func (c *cRsa) GetKey(ctx context.Context, req *v1.GetKeyReq) (res *v1.GetKeyRes, err error) {  //context.WithValue(ctx, "name", req.Name)  res = &v1.GetKeyRes{}  pub := service.Rsa().GetKey(ctx, req.Name, 2048)  res.Public = pub  res.Result = "success"  return }  // 生成公私钥 func (c *cRsa) GetKeyPri(ctx context.Context, req *v1.GetKeyPriReq) (res *v1.GetKeyPriRes, err error) {  //context.WithValue(ctx, "name", req.Name)  res = &v1.GetKeyPriRes{}  pri, pub := service.Rsa().GetKeyPri(ctx, 2048)  res.Public = pub  res.Private = pri  res.Result = "success"  return }  // push 私钥 func (c *cRsa) PushKey(ctx context.Context, req *v1.PostPublicKeyReq) (res *v1.PostPublicKeyRes, err error) {  res = &v1.PostPublicKeyRes{}  err = service.Rsa().Pushkey(ctx, req.Public, req.Name)  if err != nil {   res.Result = "push public failed"   return  } else {   res.Result = "push public success"   return  }  }  // 解密 func (c *cRsa) Decrypt(ctx context.Context, req *v1.DecryptReq) (res *v1.DecryptRes, err error) {  res = &v1.DecryptRes{}  secret := []byte(req.Secret)  if secret_, err := service.Rsa().Decrypt(secret, req.Name, req.PublicKey); err != nil {   res.Result = "Decrypt failed"   return res, err  } else {   res.Result = "Decrypt success:"   string(secret_)   return res, nil  } }  // 验签 func (c *cRsa) Verify(ctx context.Context, req *v1.VerifyReq) (res *v1.VerifyRes, err error) {  res = &v1.VerifyRes{}  sign := []byte(req.Sign)  data := []byte(req.Data)  result := service.Rsa().Verify(data, sign, crypto.SHA256, req.Name)  res.Result = result  return }  

model

package entity  // User is the golang structure for table user. type User struct {  Id          int64  `json:"id"          description:"UID"`  Name        string `json:"name"        description:"账号"`  Password    string `json:"password"    description:"MD5密码"`  Nickename   string `json:"nickename"   description:"昵称"`  Status      int    `json:"status"      description:"状态0:启用 1:禁用"`  Cpublickey  string `json:"cpublickey"  description:""`  Sprivatekey string `json:"sprivatekey" description:""` } 

service

package service  import (  "bytes"  "context"  "crypto"  "crypto/rand"  "crypto/rsa"  "crypto/x509"  "encoding/asn1"  "encoding/pem"  "firstproject/internal/model/entity"  "firstproject/internal/service/internal/dao"  "fmt"  "github.com/gogf/gf/v2/os/gctx"  "strings" )  // RAS管理服务 func Rsa() *sRsa {  return &sRsa{} }  type sRsa struct { }  /**  * 解密  */ func (s *sRsa) Decrypt(secretData []byte, name, publicKey string) ([]byte, error) {  var (   user *entity.User   ctx  = gctx.New()  )  err := dao.User.Ctx(ctx).Fields("sprivatekey").Where("name=?", name).Limit(1).Scan(&ampuser)
	if err != nil {
		return nil, err
	}
	// 解码将找到下一个PEM格式化块(证书,私钥,etc)
	block, _ := pem.Decode([]byte(user.Sprivatekey))
	var rsaPrivateKey *rsa.PrivateKey
	// 判断私钥类型
	//pkcs1
	if strings.Index(user.Sprivatekey, "BEGIN RSA") > 0 {
		rsaPrivateKey, _ = x509.ParsePKCS1PrivateKey(block.Bytes)
	} else { //pkcs8
		privateKey, _ := x509.ParsePKCS8PrivateKey(block.Bytes)
		rsaPrivateKey = privateKey.(*rsa.PrivateKey)
	}
	// 提取公钥
	block_, _ := pem.Decode([]byte(publicKey))
	publicKey_, _ := x509.ParsePKIXPublicKey(block_.Bytes)
	rsaPublicKey := publicKey_.(*rsa.PublicKey)

	blockLength := rsaPublicKey.N.BitLen() / 8
	// 服务端用给客户端公钥对应的私钥解密(如果公钥被拦截 无法识别用户 需要用到签名)
	if len(secretData) <= blockLength {
		return rsa.DecryptPKCS1v15(rand.Reader, rsaPrivateKey, secretData)
	}

	buffer := bytes.NewBufferString("")

	pages := len(secretData) / blockLength
	for index := 0; index <= pages; index++ {
		start := index * blockLength
		end := (index + 1) * blockLength
		if index == pages {
			if start == len(secretData) {
				continue
			}
			end = len(secretData)
		}

		chunk, err := rsa.DecryptPKCS1v15(rand.Reader, rsaPrivateKey, secretData[start:end])
		if err != nil {
			return nil, err
		}
		buffer.Write(chunk)
	}
	return buffer.Bytes(), nil
}

/**
 * 验签 服务端用客户端事先给服务端的公钥和签名 验签 (验签完成后才会去执行解密数据)
 */
func (s *sRsa) Verify(data []byte, sign []byte, algorithmSign crypto.Hash, name string) bool {
	var (
		user *entity.User
		ctx  = gctx.New()
	)
	err := dao.User.Ctx(ctx).Fields("cpublickey").Where("name=?", name).Limit(1).Scan(&user)
	if err != nil {
		return false
	}
	// 提取公钥
	block, _ := pem.Decode([]byte(user.Cpublickey))
	publicKey, _ := x509.ParsePKIXPublicKey(block.Bytes)
	rsaPublicKey := publicKey.(*rsa.PublicKey)
	h := algorithmSign.New()
	h.Write(data)
	// 用c端用户公钥和签名做验签
	// 客户公钥需要保存在服务端
	return rsa.VerifyPKCS1v15(rsaPublicKey, algorithmSign, h.Sum(nil), sign) == nil
}

/**
 * 生成pkcs1格式公钥私钥
 */
func (s *sRsa) CreateKeys(keyLength int) (privateKey, publicKey string) {
	// 随机生成密钥对
	rsaPrivateKey, err := rsa.GenerateKey(rand.Reader, keyLength)
	if err != nil {
		return
	}

	privateKey = string(pem.EncodeToMemory(&pem.Block{
		Type: "RSA PRIVATE KEY",
		//pkcs1
		Bytes: x509.MarshalPKCS1PrivateKey(rsaPrivateKey),
	}))

	derPkix, err := x509.MarshalPKIXPublicKey(&rsaPrivateKey.PublicKey)
	if err != nil {
		return
	}

	publicKey = string(pem.EncodeToMemory(&pem.Block{
		Type:  "PUBLIC KEY",
		Bytes: derPkix,
	}))
	return
}

/**
 * 生成pkcs8格式公钥私钥
 */
func (s *sRsa) CreatePkcs8Keys(keyLength int) (privateKey, publicKey string) {
	rsaPrivateKey, err := rsa.GenerateKey(rand.Reader, keyLength)
	if err != nil {
		return
	}

	privateKey = string(pem.EncodeToMemory(&pem.Block{
		Type:  "PRIVATE KEY",
		Bytes: s.MarshalPKCS8PrivateKey(rsaPrivateKey),
	}))

	derPkix, err := x509.MarshalPKIXPublicKey(&rsaPrivateKey.PublicKey)
	if err != nil {
		return
	}

	publicKey = string(pem.EncodeToMemory(&pem.Block{
		Type:  "PUBLIC KEY",
		Bytes: derPkix,
	}))
	return
}

func (s *sRsa) MarshalPKCS8PrivateKey(key *rsa.PrivateKey) []byte {
	info := struct {
		Version             int
		PrivateKeyAlgorithm []asn1.ObjectIdentifier
		PrivateKey          []byte
	}{}
	info.Version = 0
	info.PrivateKeyAlgorithm = make([]asn1.ObjectIdentifier, 1)
	info.PrivateKeyAlgorithm[0] = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 1}
	info.PrivateKey = x509.MarshalPKCS1PrivateKey(key)
	k, _ := asn1.Marshal(info)
	return k
}

// 返回公钥及更新数据
func (s *sRsa) GetKey(ctx context.Context, name string, keyLength int) (publicKey string) {
	privateKey, publicKey := s.CreatePkcs8Keys(keyLength)
	dao.User.Ctx(ctx).Update(fmt.Sprintf("sprivatekey='%s'", privateKey), "name", name)
	return
}

//  push本地公钥
func (s sRsa) Pushkey(ctx context.Context, public, name string) error {
	_, err := dao.User.Ctx(ctx).Update(fmt.Sprintf("cpublickey='%s'", public), "name", name)
	return err
}

// 返回公私钥

func (s *sRsa) GetKeyPri(ctx context.Context, keyLength int) (privateKey, publicKey string) {
	privateKey, publicKey = s.CreatePkcs8Keys(keyLength)
	return
}

测试

package main

import (
	"bytes"
	"crypto"
	"crypto/rand"
	"crypto/rsa"
	"crypto/x509"
	"encoding/asn1"
	"encoding/pem"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/url"
	"strings"
)

func Rsa(publicKey, privateKey string) *sRsa {
	rsaObj := &sRsa{
		privateKey: privateKey,
		publicKey:  publicKey,
	}

	rsaObj.init()

	return rsaObj
}

type sRsa struct {
	privateKey string
	publicKey  string
	// 私钥
	rsaPrivateKey *rsa.PrivateKey
	// 公钥
	rsaPublicKey *rsa.PublicKey
}

// 初始化
func (s *sRsa) init() {
	if s.privateKey != "" {
		// 解码将找到下一个PEM格式化块(证书,私钥,etc)
		block, _ := pem.Decode([]byte(s.privateKey))

		// 判断私钥类型
		//pkcs1
		if strings.Index(s.privateKey, "BEGIN RSA") > 0 {
			s.rsaPrivateKey, _ = x509.ParsePKCS1PrivateKey(block.Bytes)
		} else { //pkcs8
			privateKey, _ := x509.ParsePKCS8PrivateKey(block.Bytes)
			s.rsaPrivateKey = privateKey.(*rsa.PrivateKey)
		}
	}

	if s.publicKey != "" {
		// 提取公钥
		block, _ := pem.Decode([]byte(s.publicKey))
		publicKey, _ := x509.ParsePKIXPublicKey(block.Bytes)
		s.rsaPublicKey = publicKey.(*rsa.PublicKey)
	}
}

/**
 * 加密
 */
func (s *sRsa) Encrypt(data []byte) ([]byte, error) {
	// 客户端用服务端给的公钥进行数据加密 (客户端调用sdk)
	blockLength := s.rsaPublicKey.N.BitLen()/8 - 11
	if len(data) <= blockLength {
		return rsa.EncryptPKCS1v15(rand.Reader, s.rsaPublicKey, []byte(data))
	}

	buffer := bytes.NewBufferString("")

	pages := len(data) / blockLength

	for index := 0; index <= pages; index++ {
		start := index * blockLength
		end := (index + 1) * blockLength
		if index == pages {
			if start == len(data) {
				continue
			}
			end = len(data)
		}

		chunk, err := rsa.EncryptPKCS1v15(rand.Reader, s.rsaPublicKey, data[start:end])
		if err != nil {
			return nil, err
		}
		buffer.Write(chunk)
	}
	return buffer.Bytes(), nil
}

/**
 * 签名 客户端需要调用的接口,(客户本地的私钥和加密过的数据请求服务端)
 */
func (s *sRsa) Sign(data []byte, algorithmSign crypto.Hash) ([]byte, error) {
	hash := algorithmSign.New()
	hash.Write(data)
	//   用户私钥做签名
	sign, err := rsa.SignPKCS1v15(rand.Reader, s.rsaPrivateKey, algorithmSign, hash.Sum(nil))
	if err != nil {
		return nil, err
	}
	return sign, err
}

func (s *sRsa) MarshalPKCS8PrivateKey(key *rsa.PrivateKey) []byte {
	info := struct {
		Version             int
		PrivateKeyAlgorithm []asn1.ObjectIdentifier
		PrivateKey          []byte
	}{}
	info.Version = 0
	info.PrivateKeyAlgorithm = make([]asn1.ObjectIdentifier, 1)
	info.PrivateKeyAlgorithm[0] = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 1}
	info.PrivateKey = x509.MarshalPKCS1PrivateKey(key)
	k, _ := asn1.Marshal(info)
	return k
}

func POST(test_url string, data url.Values) {
	resp, err := http.PostForm(test_url, data)
	if err != nil {
		panic(err)
	}

	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		panic(err)
	}
	fmt.Println(string(body))
	//fmt.Println(resp.Header)
}

func main() {
	// 测试解密
	// 需要带服务端给的 publicKey 请求get_key接口获取
	publicKey := "-----BEGIN PUBLIC KEY-----\\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArDc0i4ZWuEqpbPvrHi6e\\nxLJIDHnreYMuJfeRPJq0Az0E4tsrlwQXy0hsmk5nIGwrdEBKJ30Er75O4V3SfwcU\\nFZYqnZ4vdqCIkTzwTYWGPOXb1mmbs8KuJzmmF7YfhwLH+DAbQOvJYteZqTWQiQtq\\njcw50rm8x3ifzB4QhdetJHQfdA8OaBXdzHeAAD8gtPilOi66n1lrR1CkS6uVpquP\\nRq0eVlJnJ56IfUVKsrP9bVH0dFfWcL7qXO8zJc3oJ2V45SobvXksGJbq6h3kGc99\\nU+k/bm9uppaRg/zJJ0IM26ioRQ0yl5NmIwfmVfSXlvuku47Fi5i7RMOWjW/ZJBM5\\n1wIDAQAB\\n-----END PUBLIC KEY-----\\n"
	// 私钥会在数据库查询当前用户的
	pub := strings.ReplaceAll(publicKey, "\\n", "\n")
	rsaObj := Rsa(pub, "")
	// 加密内容
	secretData, err := rsaObj.Encrypt([]byte("test"))
	if err != nil {
		println(err)
	}
	data1 := make(url.Values)
	data1["name"] = []string{"asimov123"}
	data1["secret"] = []string{string(secretData)}
	data1["publickey"] = []string{pub}
	test_url := "http://127.0.0.1:8000/decrypt"
	POST(test_url, data1) //{"code":0,"message":"","data":{"result":"Decrypt success:test"}}

	// 测试签名
	// 先push本地公钥
	public := "-----BEGIN PUBLIC KEY-----\\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA5ZPKd/oNXOp9Mhr6DnWd\\na1DEw+YjVVKKRY8edibRlvGhkAx3rKeLbNO1ZYhyYza8YPQEDjrAnZjD/prfh+HW\\nhtA39LLJjDXAjTlGb/2OsmxRAtmPALoPBbFHladV2O6ZBWI+p1sY+ODXRM1NRpKB\\n7aJut6Kg+wo/B0DwNioWPlqqH2OHxniwtTT9ZUCYQMXjCUmoa5a9LZBoFzvXmgnI\\nkeFpTeGJb0fJoZ7YUoZ+mUE5NhzXiLspcO9ZzaKkJlUSkYuJ0D5PR9s3tzIniifb\\nYrfPBWFyLIYpLEW4tvDmR3N993GRXyERJemVsZjBbnLr5mLVIYas9o0rmhEU5oMI\\nRQIDAQAB\\n-----END PUBLIC KEY-----\\n"
	data2 := make(url.Values)
	data2["name"] = []string{"asimov123"}
	data2["public"] = []string{strings.ReplaceAll(public, "\\n", "\n")}
	test_url1 := "http://127.0.0.1:8000/push_key"
	POST(test_url1, data2)

	// 签署信息
	data := []byte(strings.Repeat("test", 200))
	// 需要用户本地私钥
	rsaPrivateKey := "-----BEGIN PRIVATE KEY-----\\nMIIEvAIBADALBgkqhkiG9w0BAQEEggSoMIIEpAIBAAKCAQEA5ZPKd/oNXOp9Mhr6\\nDnWda1DEw+YjVVKKRY8edibRlvGhkAx3rKeLbNO1ZYhyYza8YPQEDjrAnZjD/prf\\nh+HWhtA39LLJjDXAjTlGb/2OsmxRAtmPALoPBbFHladV2O6ZBWI+p1sY+ODXRM1N\\nRpKB7aJut6Kg+wo/B0DwNioWPlqqH2OHxniwtTT9ZUCYQMXjCUmoa5a9LZBoFzvX\\nmgnIkeFpTeGJb0fJoZ7YUoZ+mUE5NhzXiLspcO9ZzaKkJlUSkYuJ0D5PR9s3tzIn\\niifbYrfPBWFyLIYpLEW4tvDmR3N993GRXyERJemVsZjBbnLr5mLVIYas9o0rmhEU\\n5oMIRQIDAQABAoIBAGNpgwQ/EGhK1hnLWrrGLXuaBwp5bpV035FNbzhkiN+fFIIH\\nFA98ocBnUKZ91mKmAh7Nq6/puxzDWSO4NtFldvr70S8x+FqxsAa3ZYv7NT6H7vCX\\n+veqmfSyFrh0NJVyhGqzZ0QbC45B9pXBfRPxPzgC3YTBdIognrhqY1phES7AS9hQ\\ntOfDD5B5jiAaIWXuDX9aXBJWT+NV0p59l+/xRTVen9bSVU3rl3rM1T7w5/Ax2l4G\\nvv603m4MIEMqXvufhvErmwBMNrpLIEjvy6zmfTqXoOCWoTIl0GNLQNaMulGvAf6T\\nL6xJ+kJ5BMxaeZVm4GU6QBaFpJ2gMVRekfXJHcUCgYEA6tRXywQcirvKgrb5NoGz\\nYf9Q5haXzdDbJHs6HbSySfS69fGurhaOJzywPUxa907OGbJ3zFMEpA3Z/R5Lzt5j\\nKBYXMOC7J9bN8jsPiR6RAtFIKzYDSX2/Xln3jydNLmVfvGgU4GqZmsacigNcG2hi\\nZ6qUj2j0qthPoQ7nu6YUszsCgYEA+kY7mXc+k0q++KGzm7syxHcmtP44w9llQmp0\\nLXlVm55scyYN9fbsTOIMDtNYgc4nlAcDT3vcDh/YxFAOZ3ZhFSc0aCCejxOUgV+F\\nSpWIxb22FCcN0m/yZx03hzB02P6dqxWEYVxcdushESchbvicRJUNIElyMylbDrg6\\n6Lk8en8CgYBekRSp1QYJeIadDUJfCOxMUp0pi3+miq01i8pjnBkQX1XLJYDK6ppk\\ngrQWe2FGpp2pC43i4qvDxTA8Fq9Ap54Wzo6YSGgWKxLUsaQX/A85qz386Mt6FQGz\\n5VckdxdFz9016lQ966/f/IudqKy2/NpkFPWuqv2cr2+h1HbNwpwjcQKBgQD4QBg4\\nNub0FW1ulH7jF4HZDVNwrsbBxe9CPPP2c2duUGvEoFeyxfZIoORTBGLDhykNFRO8\\nkOCLhh1vRPW0vOC5qcS7ELgWtdZVqdk+TSt48aAdR0vXlEF+9KUyzObqo0zj+hjw\\ntjvlnX+UUxs/xwzCnpKBlzjW9Mukwytz0uHhowKBgQCNk8zbbWgU8MXiylLQxcdu\\n45AFt7b8UW9H3y9I7ds/l8mQF9aHvAykpp8OSdNP5dASlYaFzq+2RaFMTUcZClxa\\ntXSxuPLAnUXDok5oP2A6SCX1LA9vJ2kxpLprh4BHaKwevbmx6qtyRHTJyc+V9L5a\\nTiD4zVzrW9Ez13heA3P4RQ==\\n-----END PRIVATE KEY-----\\n"
	rsaObj1 := Rsa("", strings.ReplaceAll(rsaPrivateKey, "\\n", "\n"))
	sign, _ := rsaObj1.Sign(data, crypto.SHA256)
	data3 := make(url.Values)
	data3["name"] = []string{"asimov123"}
	data3["sign"] = []string{string(sign)}
	data3["data"] = []string{string(data)}
	test_url2 := "http://127.0.0.1:8000/verify"
	POST(test_url2, data3) //{"code":0,"message":"","data":{"result":true}}

}

标签: 2237zjbm圆形连接器

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

 锐单商城 - 一站式电子元器件采购平台  

 深圳锐单电子有限公司