golang语言rsa加解密及签名验签

2023-05-16

golang语言rsa加解密及签名验签

  • `rsa`算法
    • 概述
    • `Rsa`结构体封装
    • 封装的优点
    • 使用案例

rsa算法

概述

rsa是一种非对称可逆的加密算法,对加密数据长度有限制,同时rsa也提供了数据的签名与验签的支持,在实际项目中被广泛应用,如:支付宝等。

golang语言对于rsa算法的实现在crypto/rsa包中,rsa包实现了PKCS#1标准的rsa加密算法。

rsa算法依赖一对公钥私钥,私钥有PKCS1PKCS8两种格式标准,一般采用公钥加密私钥解密私钥签名公钥验签

Rsa结构体封装

import (
	"bytes"
	"crypto"
	"crypto/rand"
	"crypto/rsa"
	"crypto/x509"
	"encoding/asn1"
	"encoding/hex"
	"encoding/pem"
	"fmt"
	"strings"
)

type Rsa struct {
	privateKey    string
	publicKey     string
	rsaPrivateKey *rsa.PrivateKey
	rsaPublicKey  *rsa.PublicKey
}

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

	rsaObj.init()

	return rsaObj
}

func (this *Rsa) init() {
	if this.privateKey != "" {
		block,_           := pem.Decode([]byte(this.privateKey))

		//pkcs1
		if strings.Index(this.privateKey,"BEGIN RSA") > 0 {
			this.rsaPrivateKey,_ = x509.ParsePKCS1PrivateKey(block.Bytes)
		}else { //pkcs8
			privateKey,_ := x509.ParsePKCS8PrivateKey(block.Bytes)
			this.rsaPrivateKey = privateKey.(*rsa.PrivateKey)
		}
	}

	if this.publicKey != "" {
		block, _ := pem.Decode([]byte(this.publicKey))
		publickKey,_ := x509.ParsePKIXPublicKey(block.Bytes)
		this.rsaPublicKey = publickKey.(*rsa.PublicKey)
	}
}

/**
 * 加密
 */
func (this *Rsa) Encrypt(data []byte) ([]byte, error) {
	blockLength := this.rsaPublicKey.N.BitLen() / 8 - 11
	if len(data) <= blockLength {
		return rsa.EncryptPKCS1v15(rand.Reader, this.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, this.rsaPublicKey, data[start: end])
		if err != nil {
			return nil, err
		}
		buffer.Write(chunk)
	}
	return buffer.Bytes(), nil
}

/**
 * 解密
 */
func (this *Rsa) Decrypt(secretData []byte) ([]byte, error) {
	blockLength := this.rsaPublicKey.N.BitLen() / 8
	if len(secretData) <= blockLength {
		return rsa.DecryptPKCS1v15(rand.Reader, this.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, this.rsaPrivateKey, secretData[start: end])
		if err != nil {
			return nil, err
		}
		buffer.Write(chunk)
	}
	return buffer.Bytes(), nil
}

/**
 * 签名
 */
func (this *Rsa) Sign(data []byte, algorithmSign crypto.Hash) ([]byte, error) {
	hash := algorithmSign.New()
	hash.Write(data)
	sign, err := rsa.SignPKCS1v15(rand.Reader, this.rsaPrivateKey, algorithmSign, hash.Sum(nil))
	if err != nil {
		return nil, err
	}
	return sign, err
}

/**
 * 验签
 */
func (this *Rsa) Verify(data []byte, sign []byte, algorithmSign crypto.Hash) bool {
	h := algorithmSign.New()
	h.Write(data)
	return rsa.VerifyPKCS1v15(this.rsaPublicKey, algorithmSign, h.Sum(nil), sign) == nil
}

/**
 * 生成pkcs1格式公钥私钥
 */
func (this *Rsa) 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",
		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 (this *Rsa) 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:  this.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 (this *Rsa) 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
}

封装的优点

  • 1.支持PKCS1PKCS8两种格式的私钥
  • 2.突破了加解密对数据长度的限制
  • 3.签名与验签支持多种数据签名算法
  • 4.支持生成PKCS1PKCS8两种格式的私钥

使用案例

func main() {
	//content   := strings.Repeat("H", 244)+"e"
	//content   := strings.Repeat("H", 245)+"e"
	content   := strings.Repeat("H", 24270)+"e"
	//privateKey, publicKey := NewRsa("", "").CreateKeys(1024)
	privateKey, publicKey := NewRsa("", "").CreatePkcs8Keys(2048)
	fmt.Printf("公钥:%v\n私钥:%v\n", publicKey, privateKey)

	rsaObj := NewRsa(publicKey, privateKey)
	secretData,err := rsaObj.Encrypt([]byte(content))
	if err != nil {
		fmt.Println(err)
	}
	plainData, err := rsaObj.Decrypt(secretData)
	if err != nil {
		fmt.Print(err)
	}

	data := []byte(strings.Repeat(content,200))
	//sign,_ := rsaObj.Sign(data, crypto.SHA1)
	//verify := rsaObj.Verify(data, sign, crypto.SHA1)

	sign,_ := rsaObj.Sign(data, crypto.SHA256)
	verify := rsaObj.Verify(data, sign, crypto.SHA256)

	fmt.Printf(" 加密:%v\n 解密:%v\n 签名:%v\n 验签结果:%v\n",
		hex.EncodeToString(secretData),
		string(plainData),
		hex.EncodeToString(sign),
		verify,
	)
}

输出样例:

公钥:-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAq2FqPV4IzgxdnhoF3QdY
Sxxy8oLNMd02rg04Ye9uLdfJu//898u6nruD9u7zXy6lbdRoP7XdXq1HIGlQGX+T
WGYzj/39ul4ZPdROxRKhsp/OaLiMhyWDaZ00W6UyRddWKHEI+XL3GfzFOoWFkT99
tgC0mHoxGX8XiRJ3X86IZdDvyTgbmder+GB7D2k4ErFPzMIvDi22OGBWcW+r1Lmr
MWuHF1MIc4g6oEoXMSDZUVbzsNeyUVSgl0B5icGwUTtKpOmGCnh2AjyCIF5euzG5
jZE26vGP7Taey7vAAPgtNJq1SQbeQJTdh63LlGWlNPfZ5VNkI9+MwLIlg9fQvK/B
OQIDAQAB
-----END PUBLIC KEY-----

私钥:-----BEGIN PRIVATE KEY-----
MIIEuwIBADALBgkqhkiG9w0BAQEEggSnMIIEowIBAAKCAQEAq2FqPV4IzgxdnhoF
3QdYSxxy8oLNMd02rg04Ye9uLdfJu//898u6nruD9u7zXy6lbdRoP7XdXq1HIGlQ
GX+TWGYzj/39ul4ZPdROxRKhsp/OaLiMhyWDaZ00W6UyRddWKHEI+XL3GfzFOoWF
kT99tgC0mHoxGX8XiRJ3X86IZdDvyTgbmder+GB7D2k4ErFPzMIvDi22OGBWcW+r
1LmrMWuHF1MIc4g6oEoXMSDZUVbzsNeyUVSgl0B5icGwUTtKpOmGCnh2AjyCIF5e
uzG5jZE26vGP7Taey7vAAPgtNJq1SQbeQJTdh63LlGWlNPfZ5VNkI9+MwLIlg9fQ
vK/BOQIDAQABAoIBAQCHpsnS3TWW8o6/b9WoSAIJIfGSJxqIF5MKXYh9bGkHfEA/
wLXY5bdHoSEpOaYFdwSWVIRXuXoJUJp1+yXdqO9WDz9NADvvYkAUgpH+x2qZ2ogk
t77z0iucU0R4LeAHDBU0WZRC7k7MkRkD41//wgOdJh3MexuWFNTqOGWove+UtmqE
CxsqQ4VcGjiQzJu6mqYMvVQuHIpknj0gl+c6zNU49rHWObyxXzOF4vGBw2BhJPEq
UyON4eJuRb49WiU9THug73sjCYe1t5vvrvXl+rkW6+ribFMTkSWPigumN7JEV3uK
2IKXEOHdB6Vcy6ihXggdEoO67f5UNrbHy4f4TSLJAoGBAMUr2SvJDg9EwaPLdpwO
VIStPp//Pjy2fnMdYlz1pMk2t6IW6lOFeqNxHjOOxYfnYO2L3dZ1gHjPIz9QX5Zm
2PLxsTv1PsGKkwzniIIOetJdBwd+wFd7HtDLjoQEamkz5dcgDR26ySbrmV7H/wZg
GMmr8+LkD5VhM7FSn5/ExbZDAoGBAN6DpDV2PvqeAdCMeh917PZbZhAA8i0yNUMB
MpGHx86nm2SgfmgQ8b4gTghjCS24nnSI8EaMkyjROS/TWDLZoErcqy+/O+wKJaKM
gmmiZa1QMrAi80xTFIMsHD34GIG+qsf6+xZYUSv8KE+t92W/czSwRlKG7/0MG0E4
gIe6JtjTAoGAGDgEmv49Pd7iMi5hyVVxSELHeHuvt2FrMtSfKm/558VS1RQfgFba
84yHeynEVac0HrmZbChOuYgn+jTzKNRFPcI2VPkQ1lEhMuqVt/PzXjeTD3agRZ6X
8GmwfcLVF0sKplwHgGlbH+68jgne53eSU+NNN8dvqpef894EQWm4J2UCgYBcoerz
grV3Od5Bhqm0fTBX4vbbRLmNDTDVIyN9KEyLAIWVX6cgBaXN4774iNoiWZBFrVhx
1kXRIUCwY0h9atHrOHBfoTn96r9+KwaDmWLAwvlHEFW++Xs5nFxpg+YX5VtNg3OR
+tRX/lJ90UuD5S69yYCNDLXN34NdJHuFhX50lwKBgGqdUCKfM1oiD1Cnnr7YtIIp
6c3PmPn0cdK+Wb7rTp/u8gU90LSDRgA8GhTcrV6dj/0mmcvDiiAI+FPnWrDNQr97
2IkhMbQi651P+TyDIb8uehCjKI58SqvT0u8wqyHqKn6lEW6TZ8qnyO9QFBlJHA3p
cMR9qOxIQay/heVbOVTz
-----END PRIVATE KEY-----

 加密:3e44f56871841096e218dadd7d519b058a267ead9511bdddcd8e69a87a9a730438a0d017819c4f68e688fbf2638446f9924ccc9505c7b9c5d04bf45f9f36c4290ea9bf63a53d2b59fa8179f536c03a266a585bfe6336b17268a9c628e7e1f125e8e63a7bd91ff733ed2b08cb47d8f1ebd2b6be38074367f6d7dba5653d52635986e3c1716be406b1ffcf9eb67b84a87f368052ce1f28bd6f6776bc159bb56c62eb9f6d0b24b09cef89b5db3b1550c25ac64a2ab4b8901283d67846e8f408c59b65d00ea570abb0f7025b3ddf43511f04dde2a316fd8b46158691a330f54e82a75d897c85a5bc7175e20cc6e692fcf7125d0b5cf2af170a843798874a3cb83228fa3c9f83ac1f7b26d9e269d93313a8c7e1013613f624c82352760a3539b10468e6b75bf58b6d0d4e3179cd73eacd1f790fc0baa5593289177e1cc2b27fb4b8c14da48ae6cd26b939cd5888ce67401e5b5ac02ba3a8c76b64f16c7fe0ff2e2430d06924a36e331e292110f2758977239984260c8f8908850f93ebeddf112a4ad9694ac1271bd44dc628f82aad36c548ccf3a398f41a415c56816e9d0c46a35d1eeac4c6eb69ab064235bba249f20dc6a8e1b8625bf77fbb266dd0e95188251d5c87001a12d6d58a1ef479aa5fa50aac8606ee09e73e7d5ed965c0d73048df9c916232ec950056a47a8873e8debc76c2d15f183fce08db001fed87f923f09928c7c4ff18626e2d231c5caafc6a414e4b6f6da0d5d66bf0d042eb75c51c8b5b61035cfa75fae4ef51afa36386a105178fa4d65e5c565888d813837e61c38309abe2cc967b9a510c1fe01ef2ceacdbccc8b5fd90c9600b5a5028fc8451f24e38cbb4b64fddcb6cefc7f1d7289da033293cd72ff2bc5d1997adfe04ef48b1283c680b330bb62d35fd88cecb46b3c5e4d01c1383ad0c7ccaa0266b5641cdae22fb922b75db7c481b8ddb991a5c767d2fb25dbd4410c94f2f5afd68ecede907452ed491931063e4ca9271cbea802db99f69f3b573ba699c3455fe9f307185f20c21829881ba2c9165e6d191ed527293f3b324641ac91077a26a411f9fe7769bce4e168ea1beb6c6de2a3c0747ba3750fbd4e5b0c7169698158a94aa5ea4c2fa7979029b9ed1075d8ebe8d4fc8d9fd8bb424f6313c6cd43bff584ed73723614658f43c1a1b7de19f1f467f0fddbe5be6d93d82c467dcaefbb83881c29f3bd0bbd57b9e64522b8e603e5aab589257d889d80d7db15e4fbb3716daee48627feb9c105c1555d488028421f833f8676273bc663f06c8fe3590ade6357ff2fe0f0f6a99c8459a158a353e524c0a738a6f6b127c797d6594e2a987063c9b111d190be5289b9ccae19d9348ec5f8b257885c1974f734dca8e0992bd4c06dfa5f7bf56aab48103761755eb21d3ac95bee66e2ff6985d6ff20e677776d652e5f83727fa254c7d28c070eca7b5597830e0d3c844666ccace00242f85d92dae9ed47cc403d2ad39d827e3a8e6a4ba1feb7c097b1c9dbf00214a7f4cff6eb291439d7bc9143bcb39616c5d2b9d27d7f18810823b1eccc6a95fb98d2c6060963393c77951986af6330d801221fc037152f31fc07936fbe6b49c99fd69f0b0f30a5268ad601505048be8f9976bbe1513e93a0ddaa57831c8f53cdb4e99dc9ec81f9b99d1a2aa02bffa1a08bbeb823919a42af4b0a465d0b5d59db1bb377599926016b0b9c3fb38741e8130589fd1e48d0ff96557680e19909c16e0cfc954206427683ff81632ea5cc288409730ad43aa2c36305c7fd853f912ea88a7f4038ca95b567fb540ae842c9853f1b250cd822c7da2eb042082657bbaf79effd0b2922fd073edeb8334b1b009afd5476077cd770552912f78a63bcf4cb66acf29a6f6004b3e5b6cd46489a0401de0efd549037fc706be79707f991da214ae91e3d4514fedb14ea1bda5fadd7c2a59038ae0749250215dd44ef995918f097889cd5e653c97dc13b7f232d6cda9e823037a72a6b6542be9ace101e51dc76815e6ab729ecbed3843a6831147050c7bb333f85db091317ca64a12af5df1e936709ddf776f05f731fd2ab287785c83d72588c2fabc284c88c855dc2b1e57afe4edc10bc148eef4da7732e3cacb4b7091b6abe6e8d7e28bd28b4df8ad4ed076787550900169edab5cf8c7ea54da8ece91261ba602a958b57827077b9895924febb00d95151cc34a465a541b07239db4a9f899db8e2fb9d607b165fddb93232e30deab4c773f790496a8b2ee2087449ae71cce3659648c3430f770aad447865f58f357f72575cc79d960d65593a3f78a0623e333373228cf4442c16acb76d5258a92361035a7591bebd5258f7c06fc21936dddc2ad89caf85c9d89a551aa06fc5b1949dfa4961bf209ec680efc568b0ad6bb2ad3b04178a293efa26815d7b634cdd0920b3fc95e7dcad7a27fe57541d92f73b1f52b15c7e54e16277f919067d8e7f14a9e62256af4ba53e0100472965dbabfe1270f4a089960ce870ea9f76fc1ff029c8c8b1efe2e462b1828a65f65ba922c31443593115a3fd0569112597a8ed0fc2200a933a7afdbeae357c885da6e95bbe8f421186b7fd13d3e488492339d74be35c32cc36e1d70d86fd786e6ac3373224d79221d453d8f64d12a9c979bda0712173da3196a19bd600eea4811329e71fba39466058676920cfcdcc58637a39efb88aef726dd1b9b3bc56dfcacf4afe99515ea160c54f5b93fedc66fdcb2d2e206bf61eb73dda5380a41c6135dcd4f983f92fedc2ca9db3fd928b0072bc8d8ab88b8ba4f853b3ce335dbddd1ee94700c2a234fae16949b6fc6bb48c935e114b3f83297e9321241c7ed5c3ccf81a1a7f5f400126e78c06f9c76c890ec725365732c6bd53f7bfb114160cdfee29f3d89c8f9cc7a36fe8a3752abe7a11da82f23416ae308cbb7a451fc948791daea6b3b1ca92e17780fe3e5429d124f718b16dde05385de51af7b822f4dcc0212f7fa93053a890139803047ff7b55cd34bacef917f4e79b6bd062f5cf772db75befa6d9ab795d0434aefb2abb85877f14faecafbc26bb8216bd4a7a6badaaa0d3335c5e5f00725331d77c956458890f799407561a6c3704f4446102d6e903104c4dc8a839de492651b4621aba5bad58adfab642a1f8cf58e04596cc814bf19daf5c8c00ab18805fb7b4630fd8b827609ecf5b7a5d60b650134433aa9f0e9edab3d98baca850906ca81b9cda8e6b4fab413a01e7402d49f5d52fa029d8018252c59922f467fa13d827de7d4155571fb601d73bf19bb7bb4b1f7a2d860b99c3f5d37d2163b4295f878620ae01713a1c64a1d505ea9bd93fc5da8cf52ec66abb91f53b6410e9c783f8ae4f921c1e2ad4399071b955d4f0d45eda2be0f25cc11da293e51fbb8a8f03d4c7247a5891e7b91e1d2e2119b9757370f741fc864653d904e616d75b3596a2da354c031320ef8bd491e7652ca1fe8e3c25bb1f404497210b921d678d888b19f23c14ff9ff54b1c83df577ce7e473e5fcd9c71e8be9faea4ae4707a152b3b0383fb94a1d6bc5248ccd5ecd8e1ef687e088c09f32995cf478e902242f43bc6aedebc91943f851fc693db04e1435d1bbccba3f2f47c4e50337f30b4fce1f
 解密:HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHe
 签名:7125c98bb2443b975d41af34f480c6d0f08522dd88de61216759082bfe643a09b4a4c1aadf03c4607abe54ed6e69ac12347d08f70816539929ffbec5fc972a4cda8cf4d09bcf4fff6e51140fb7766712ec0cd30a02bd1690d7f136c507afee84b5456bfedbb109088dc0db4a0a31e4d791f06e8e6340797822d5ca96ac7fa58ed5ad9f36d2edcde53d1de07d1691b66e11d14fd3cba36e8947d48e811fbf414b901d9d8d968a2663a1dcc3f0531da64f0bbad2fae666173492fc1d88d14e92997639de21d32b8c7137ee3ed013c9fd258f383c271e7243ee24f64a94f58e77adf2ab2d22fad63022471e2e7bbf8a8dbca7400a17026f51c25b9374e2ec3c7
 验签结果:true
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

golang语言rsa加解密及签名验签 的相关文章

  • dpkg: 处理软件包 xxx (--configure)时出错解决方法

    问题 xff1a dpkg 处理软件包 libicu dev configure 时出错 xff1a 依赖关系问题 仍未被配置 dpkg 依赖关系问题使得 libxml2 dev amd64 的配置工作不能继续 xff1a libxml2
  • oracle 删除表以及回复数据

    找回删除的表 select object name original name partition name type ts name createtime droptime from recyclebin WHERE original n
  • 银行卡信息查询

    银行卡bin 银行卡信息 请移步到github xff1a https github com burningmyself bank
  • ProcessDefinition是干这个用的

    流程定义ProcessDefinition是对业务过程的完整描述 xff0c 例如请假流程定义 报销流程定义等 流程定义的管理包括部署流程定义 查询流程定义 查看流程定义图和删除流程定义 1 部署流程定义 使用RepositoryServi
  • 截取字符串的三种方法

    众所周知 xff0c java提供了很多字符串截取的方式 下面就来看看大致有几种 span class hljs number 1 span span class hljs built in split span 43 正则表达式来进行截取
  • Iterator主要有三个方法:hasNext()、next()、remove()详解

    一 Iterator的API 关于Iterator主要有三个方法 xff1a hasNext next remove hasNext 没有指针下移操作 xff0c 只是判断是否存在下一个元素 next xff1a 指针下移 xff0c 返回
  • @ModelAttribute用法详解

    转载于 xff1a https blog csdn net harry zh wang article details 57329613 之前项目中并自己并没有怎么使用到过 64 ModelAttribute这个注解 xff0c 接手一个老
  • mysql除法运算保留小数的用法

    参照 xff1a https www cnblogs com owenma p 7097602 html 在工作中会遇到计算小数而且需要显现出小数末尾的0 xff0c 我们会用到DECIMAL这个函数 xff0c 这是一个函数非常强悍 xf
  • IDEA—点击文件代码与目录自动同步对应

    关注微信公众号 xff1a CodingTechWork xff0c 一起学习进步 引言 在使用IDEA的时候 xff0c 我们Ctrl 43 Shift 43 F搜索文件后 xff0c 总是要慢慢找文件在哪个包路径下 如查看路径顶端 xf
  • springboot打包完成之后无法读取到resources下的资源文件

    File privateKeyFile 61 ResourceUtils getFile classpath wx pfx PrivateKey privateKey 61 getPrivateKey privateKeyFile priv
  • 接口签名实现拦截的两种方式

    1 采用spring的aop思想进行拦截 需要自定义注解 xff0c 然后定义切面 xff08 五大类 xff09 然后在定义 xff0c 可以获取所有的参数 2 拦截器的实现方式 自定义拦截器 xff0c 然后对拦截器进行配置即可 配置
  • Java程序员利器,lombok神搭档:delombok插件

    Lombok是一款非常实用Java工具 xff0c 它可以帮助开发人员减少样板代码 xff0c 使开发人员专注业务逻辑 xff0c 在Java界几乎无人不知 但也有一些明显的缺点 xff0c 例如 xff1a 对插件强依赖 xff0c 在团
  • C++bind函数

    1 基本概念 bind函数定义在头文件 functional 中 可以将 bind 函数看作一个通用的函数适配器 xff0c 它接受一个可调用对象 xff0c 生成一个新的可调用对象来 适应 原对象的参数列表 C 43 43 Primer
  • C++值的分类 —— 摘自维基百科

    在C 43 43 11 xff0c 对于值的分类 xff0c 要考虑标识 xff08 identity xff09 与可移动性 xff08 movability xff09 xff0c 二者的组合产生了五种分类 xff1a 基础值类型 左值
  • pytorch 深度学习入门代码 (一)线性回归代码实现

    34 34 34 一维线性回归代码实现 34 34 34 import torch from torch autograd import Variable import matplotlib pyplot as plt import tor
  • pytorch 深度学习入门代码 (三)Logistic 回归代码实现

    span class hljs string 34 34 34 Logistic 回归的代码实现 34 34 34 span span class hljs keyword import span matplotlib pyplot spa
  • pytorch 深度学习入门代码 (四)多层全连接神经网络实现 MNIST 手写数字分类

    net py span class hljs keyword import span torch nn span class hljs keyword as span nn span class hljs class span class
  • CentOs云服务器部署项目全流程

    目录 序工具准备putty安装及使用pscp安装及使用 环境安装及配置serverjre 或jdk 安装及配置mysql安装及配置Tomcat 安装及配置 项目部署上传war包至服务器tomcat无法启动常见问题去除端口号和目录名访问项目项
  • 快速上手MybatisPlus

    首先附上mybatis plus官方文档 本篇参考官方文档记录spring mvc项目接入mybatis plus的全流程及一些问题的解决方案 xff0c 建议优先参考官方文档 开始之前 xff0c 假设数据库已建好并已能正常访问 依赖配置
  • FTP工具类一

    public class FTPClientUtils public static String FTPCONFIG 61 34 config ftpConfig properties 34 private static String LO

随机推荐

  • 在 SourceTree 中使用 git rebase (变基)

    原始状态 假如我们要在 master 分支上进行开发 xff0c 在远端的 master 分支上右键 xff0c 检出 一个自己的开发分支 dev 1 做一些开发 xff0c 提交到本地 xff0c 不要推送 xff08 push xff0
  • 云服务器搭建部署全流程

    本篇记录在centos7 3上部署web项目的全流程及一些问题的解决方案 工具准备 putty安装及使用 PuTTY可用来在windows上连接linux服务器 xff0c 可去PuTTY官网下载安装如果不想每次登录都输入密码 xff0c
  • 三种获取字节码对象的方式及区别

    方式一 xff1a 对象 getClass 方法是 根对象Object的方法 是其他类继承Object的getClass方法 方式二 xff1a 类名 class xff0c 你可以理解为字节码本身就是静态的 xff0c 类加载的时字节码就
  • 关于接口与Object 类的关系

    看到这个标题 xff0c 你或许就会想好自己的那份答案 但事实上这个确实没有答案 xff0c 至少没官方证明它们之间的基友关系 看法一 xff1a 因为老师说 xff0c 你可以把接口看作是特殊的类 xff0c 所以不假思索的就认为接口也
  • 单词博弈Java实现(借鉴“miss若尘”博客中写的解题思路)

    单词博弈Java实现 xff0c 已经通过庞果网的用例测试 代码如下 import java util HashMap public class WordGameFinalTest public static int who String
  • mysql安装时的粗心错误:last error unable to update security settings. access denied for user 'root' @ 'localh

    来自 梦想家haima 39 s blog gt http blog dreamwe cn 这个报错出现在mysql最后 当你看到mysql的最后一步需要设置密码可能你开心得很 Mysql就快安装好了 赶快输入三行密码都是root 结果报下
  • @SuppressWarnings

    简介 xff1a java lang SuppressWarnings是J2SE 5 0中标准的Annotation之一 可以标注在类 字段 方法 参数 构造方法 xff0c 以及局部变量上 作用 xff1a 告诉编译器忽略指定的警告 xf
  • 欢迎使用CSDN-markdown编辑器

    欢迎使用Markdown编辑器写博客 本Markdown编辑器使用StackEdit修改而来 xff0c 用它写博客 xff0c 将会带来全新的体验哦 xff1a Markdown和扩展Markdown简洁的语法代码块高亮图片链接和图片上传
  • Linux之强大的awk

    来自 梦想家 Haima s blog gt http blog dreamwe cn awk简介 awk是Linux中的一个命令 xff0c 用来做文本处理与分析 xff0c 功能简单强悍 xff0c 同时它也是一门编程语言 awk处理文
  • 手机抓包charles使用

    使用的是charles window 之前使过fiddler但是感觉并没有charles好用以及一目了然 链接 https pan baidu com s 1NMNXa8M4niLObQKIsCNL3A 提取码 2wsa 安装包可以通过连接
  • 安卓Tinker热更新接入踩坑(minSdkVersion 21)

    哎哟 xff0c 这个坑啊 我项目采用的是ARouter 43 Tinker 我接入的是tinkerpathchttp www tinkerpatch com Docs intro按照文档对接 xff0c 我采用的是reflectAppli
  • Android 解压和重新打包system.img

    开始我们的工作前 xff0c 请记住 xff0c Linux一定要学会用file命令分析文件类型 xff0c 这样才好入手 xff0c 否则错了都不知道怎么回事 xff01 xff01 xff01 1 解压system img 先用file
  • Jetpack系列学习笔记整理一 之LifeCycles

    学习最好的途径就是官网和github Demo xff0c 先放链接 xff0c 想看自行跳转 xff1a 官网 xff1a https developer android com topic libraries architecture
  • 获取安卓位置信息

    别忘了添加权限 xff1a lt uses permission android name 61 34 android permission INTERNET 34 gt lt uses permission android name 61
  • 安卓与html混合开发之原生与js相互调用

    原生和html的优缺点就不多说了 xff0c 有些特定条件下用html页面可以很方便 xff0c 也很容易更新和维护 xff0c 那么这就涉及到html与安卓原生的交互和通信 接下来我要分享的是html调用原生的弹窗和位置信息 xff0c
  • 应用保活--杀死进程也能收到推送消息

    我选取的是极光推送 xff0c 当把进程杀死时候就接受不到推送过来的消息 这是因为我使用的是小米手机 xff0c 小米和华为手机属于那种深度定制安卓系统 xff0c 需要用户的操作才能够实现应用 保活 的目的 小米 MIUI 自启动管理 x
  • 安卓原生与vue前段相互调用

    之前写过一个博客是安卓原生与JS交互的博客 xff1a http blog csdn net jhl122 article details 53406623 那是正常情况下的交互 xff0c 但是如果前段人员使用vue开发就会产生一个问题
  • CMake 编译时报错 ninja: error: ......missing and no known rule to make it

    Build command failed Error while executing process F Android sdk cmake 3 6 4111459 bin cmake exe with arguments build E
  • 数据类型和Json格式

    1 前几天 xff0c 我才知道有一种简化的数据交换格式 xff0c 叫做yaml 我翻了一遍它的文档 xff0c 看懂的地方不多 xff0c 但是有一句话令我茅塞顿开 它说 xff0c 从结构上看 xff0c 所有的数据最终都可以分成三种
  • golang语言rsa加解密及签名验签

    golang语言rsa加解密及签名验签 96 rsa 96 算法概述 96 Rsa 96 结构体封装封装的优点使用案例 rsa算法 概述 rsa是一种非对称的可逆的加密算法 xff0c 对加密数据长度有限制 xff0c 同时rsa也提供了数