当前位置:网站首页>RSA encryption and decryption signature verification
RSA encryption and decryption signature verification
2022-04-23 09:09:00 【Asimov__】
api
package v1
// get request
import "github.com/gogf/gf/v2/frame/g"
type GetKeyReq struct {
g.Meta `path:"/get_key" method:"get" summary:" To obtain the public key " tags:"RSA"`
Name string `json:"name" v:"required# account number " dc:" account number "`
}
type GetKeyRes struct {
//g.Meta `mime:"text/html" type:"string" example:"<html/>"`
Result string `json:"result" dc:" Return public key "`
Public string `json:"public" dc:" Public key "`
}
type GetKeyPriReq struct {
g.Meta `path:"/get_key_pri" method:"get" summary:" To obtain the public key " tags:"RSA"`
}
type GetKeyPriRes struct {
//g.Meta `mime:"text/html" type:"string" example:"<html/>"`
Result string `json:"result" dc:" Return public key "`
Public string `json:"public" dc:" Public key "`
Private string `json:"private" dc:" Public key "`
}
type PostPublicKeyReq struct {
g.Meta `path:"/push_key" method:"post" summary:" The user uploads the public key " tags:"RSA"`
Public string `json:"public" v:"required# Public key " dc:" Public key "`
Name string `json:"name" v:"required# account number " dc:" account number "`
}
type PostPublicKeyRes struct {
Result string `json:"result" dc:" result "`
}
type VerifyReq struct {
g.Meta `path:"/verify" method:"post" summary:" attestation " tags:"RSA"`
Sign string `json:"sign" v:"required# Signature " dc:" Signature "`
Name string `json:"name" v:"required# account number " dc:" account number "`
Data string `json:"data" v:"required# Sign the message " dc:" Sign the message "`
}
type VerifyRes struct {
Result bool `json:"result" dc:" Signature verification results "`
}
type DecryptReq struct {
g.Meta `path:"/decrypt" method:"post" summary:" Decrypt " tags:"RSA"`
Secret string `json:"secret" v:"required# Ciphertext " dc:" Ciphertext "`
Name string `json:"name" v:"required# account number " dc:" account number "`
PublicKey string `json:"publickey" v:"required# Public key " dc:" Public key "`
}
type DecryptRes struct {
Result string `json:"result" dc:" Decryption result "`
}
controller
package controller
import (
"context"
"crypto"
v1 "firstproject/api/v1"
"firstproject/internal/service"
)
var (
Rsa = cRsa{}
)
type cRsa struct{}
// To obtain the public key
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
}
// Generating public and private keys
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 Private key
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
}
}
// Decrypt
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
}
}
// attestation
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:" account number "`
Password string `json:"password" description:"MD5 password "`
Nickename string `json:"nickename" description:" nickname "`
Status int `json:"status" description:" state 0: Enable 1: Ban "`
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 management service
func Rsa() *sRsa {
return &sRsa{}
}
type sRsa struct {
}
/**
* Decrypt
*/
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(&user)
if err != nil {
return nil, err
}
// Decoding will find the next PEM Format block ( certificate , Private key ,etc)
block, _ := pem.Decode([]byte(user.Sprivatekey))
var rsaPrivateKey *rsa.PrivateKey
// Determine the type of private key
//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)
}
// Extract public key
block_, _ := pem.Decode([]byte(publicKey))
publicKey_, _ := x509.ParsePKIXPublicKey(block_.Bytes)
rsaPublicKey := publicKey_.(*rsa.PublicKey)
blockLength := rsaPublicKey.N.BitLen() / 8
// The server decrypts with the private key corresponding to the public key given to the client ( If the public key is blocked Unrecognized user You need a signature )
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
}
/**
* attestation The server uses the public key and signature given to the server by the client in advance attestation ( Decrypt the data only after the signature verification is completed )
*/
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
}
// Extract public key
block, _ := pem.Decode([]byte(user.Cpublickey))
publicKey, _ := x509.ParsePKIXPublicKey(block.Bytes)
rsaPublicKey := publicKey.(*rsa.PublicKey)
h := algorithmSign.New()
h.Write(data)
// use c Verify the public key and signature of the end user
// The customer's public key needs to be saved on the server
return rsa.VerifyPKCS1v15(rsaPublicKey, algorithmSign, h.Sum(nil), sign) == nil
}
/**
* Generate pkcs1 Format public key private key
*/
func (s *sRsa) CreateKeys(keyLength int) (privateKey, publicKey string) {
// Randomly generate key pairs
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
}
/**
* Generate pkcs8 Format public key private key
*/
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
}
// Return public key and update data
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 Local public key
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
}
// Return public and private key
func (s *sRsa) GetKeyPri(ctx context.Context, keyLength int) (privateKey, publicKey string) {
privateKey, publicKey = s.CreatePkcs8Keys(keyLength)
return
}
test
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
// Private key
rsaPrivateKey *rsa.PrivateKey
// Public key
rsaPublicKey *rsa.PublicKey
}
// initialization
func (s *sRsa) init() {
if s.privateKey != "" {
// Decoding will find the next PEM Format block ( certificate , Private key ,etc)
block, _ := pem.Decode([]byte(s.privateKey))
// Determine the type of private key
//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 != "" {
// Extract public key
block, _ := pem.Decode([]byte(s.publicKey))
publicKey, _ := x509.ParsePKIXPublicKey(block.Bytes)
s.rsaPublicKey = publicKey.(*rsa.PublicKey)
}
}
/**
* encryption
*/
func (s *sRsa) Encrypt(data []byte) ([]byte, error) {
// The client encrypts the data with the public key given by the server ( Client calls 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
}
/**
* Signature The interface that the client needs to call ,( The client's local private key and encrypted data request server )
*/
func (s *sRsa) Sign(data []byte, algorithmSign crypto.Hash) ([]byte, error) {
hash := algorithmSign.New()
hash.Write(data)
// Sign with the user's private key
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() {
// Test decryption
// You need to bring the server to publicKey request get_key Interface acquisition
publicKey := "-----BEGIN PUBLIC KEY-----\\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArDc0i4ZWuEqpbPvrHi6e\\nxLJIDHnreYMuJfeRPJq0Az0E4tsrlwQXy0hsmk5nIGwrdEBKJ30Er75O4V3SfwcU\\nFZYqnZ4vdqCIkTzwTYWGPOXb1mmbs8KuJzmmF7YfhwLH+DAbQOvJYteZqTWQiQtq\\njcw50rm8x3ifzB4QhdetJHQfdA8OaBXdzHeAAD8gtPilOi66n1lrR1CkS6uVpquP\\nRq0eVlJnJ56IfUVKsrP9bVH0dFfWcL7qXO8zJc3oJ2V45SobvXksGJbq6h3kGc99\\nU+k/bm9uppaRg/zJJ0IM26ioRQ0yl5NmIwfmVfSXlvuku47Fi5i7RMOWjW/ZJBM5\\n1wIDAQAB\\n-----END PUBLIC KEY-----\\n"
// The private key will query the current user's password in the database
pub := strings.ReplaceAll(publicKey, "\\n", "\n")
rsaObj := Rsa(pub, "")
// Encrypted content
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"}}
// Test signature
// First push Local public key
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)
// Sign the message
data := []byte(strings.Repeat("test", 200))
// The user's local private key is required
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}}
}
版权声明
本文为[Asimov__]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/04/202204230904264934.html
边栏推荐
- MySQL小練習(僅適合初學者,非初學者勿進)
- [Luke V0] verification environment 2 - Verification Environment components
- 501. 二叉搜索树中的众数
- LeetCode_ DFS_ Medium_ 1254. Count the number of closed islands
- PCTP考试经验分享
- 资源打包关系依赖树
- Project upload part
- Automatic differentiation and higher order derivative in deep learning framework
- L2-3 romantic silhouette (25 points)
- Cadence process angle simulation, Monte Carlo simulation, PSRR
猜你喜欢
To remember the composition ~ the pre order traversal of binary tree
【SQL server速成之路】数据库的视图和游标
Emuelec compilation summary
Arbre de dépendance de l'emballage des ressources
Redis Desktop Manager for Mac
Introduction to GUI programming swing
The K neighbors of each sample are obtained by packet switching
Star Trek's strong attack opens the dream linkage between metacosmic virtual reality
调包求得每个样本的k个邻居
L2-024 部落 (25 分)(并查集)
随机推荐
Colorui solves the problem of blocking content in bottom navigation
Rembg split mask
Non duplicate data values of two MySQL query tables
Valgrind and kcache grind use run analysis
tsdf +mvs
Initial experience of talent plan learning camp: communication + adhering to the only way to learn open source collaborative courses
Detailed explanation of delete, truncate and drop principles in MySQL database
论文阅读《Multi-View Depth Estimation by Fusing Single-View Depth Probability with Multi-View Geometry》
Little girl walking
js 原型链的深入
First principle mind map
A must see wechat applet development guide 1 - basic knowledge
OpenCV中的图像处理 —— 轮廓入门+轮廓特征
Star Trek's strong attack opens the dream linkage between metacosmic virtual reality
2D 01 Backpack
valgrind和kcachegrind使用运行分析
Is Zhongyan futures safe and reliable?
RSA 加密解密签名验签
Latex mathematical formula
Taxable income