golang中關於RSA加密、解密、簽名、驗籤的通用處理方式

前言

我在golang中關於RSA加密、解密、簽名、驗籤的總結一文中介紹了常見的一些使用情況,並做了一些針對性的方法實例。但鑑於實例中部分參數稍微變化則需要調整整個方法,本文則從通用的角度去處理這些差異點,正確在可設置的範圍內實現通用的方法。

方案說明

RSA目前常用的就是加密、解密、簽名、驗籤相關的內容,我們則從這4個方向去做通用的解決方案。以下是具體的情況總結,與前言中提到的文章有關

1.私鑰的格式

(1) PKCS1

(2) PKCS8

兩者可以相互轉化,PKCS8主要用於JAVA中,PKCS1用於其他語言中,當然golang中兩種格式都可以使用

2.摘要算法

目前最常用的摘要算法方式如下:

(1) MD5

(2) SHA1

(3) SHA256

(3) SHA512

如目前支付寶中:使用了RSA(SHA1)和RSA2(SHA256)兩種簽名算法,祕鑰越長,摘要的長度越長,信息越安全。

3.字符串編碼格式

目前最常用的信息編碼格式如下:

(1) 直接輸出爲string

(2) 經過HEX編碼後轉爲string

(3) 經過Base64編碼後轉爲string

方案設計

我們針對方案說明中的情況均做了處理,作爲可設置項。一下代碼對應相應的設置項。

//私鑰格式
type Secret uint
const (
	PKCS1 Secret = 1 + iota
	PKCS8
)

//摘要算法,對應crypto package內的算法
type Hash uint
const (
	MD5        Hash = 1 + iota
	SHA1
	SHA224
	SHA256
	SHA384
	SHA512
	SHA512_224
	SHA512_256
)

//字符串編碼格式
type Encode uint
const (
	None Encode = 1 + iota
	HEX
	Base64
)

同時考慮到更一般的使用情況,我們把祕鑰信息單獨開來,

//SecretInfo private & public key info
type SecretInfo struct {
	PublicKey          string //公鑰
	PublicKeyDataType  Encode //公鑰編碼格式
	PrivateKey         string //私鑰
	PrivateKeyDataType Encode //私鑰編碼格式
	PrivateKeyType     Secret //私鑰類型
}

考慮到後期我們可能會加入RSA之外的加密算法如DES(事實上,我正在準備加入),我們使用接口,便於擴展。

type HandleFunc interface {
	setSecretInfo(secretInfo SecretInfo)
	Encrypt(inputData string, outputDataType Encode) (string, error)
	Decrypt(inputData string, inputDataType Encode) (string, error)
	Sign(inputData string, hashType Hash, outputDataType Encode) (string, error)
	VerifySign(inputData string, hashType Hash, signData string, signDataType Encode) (bool, error)
}

我把這些內容提交到github中的gocrypt項目了,rsa中具體的實現見gocrypt代碼,歡迎star和fork。

使用說明

更具體的說明見github gocrypt哦。

使用方法

go get github.com/yuchenfw/gocrypt

1.設置公私鑰信息

    secretInfo := gocrypt.SecretInfo{
		PublicKey:          "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyoiAraTnAbCoqGVOKugFDM2/ms2szXmb3zTOU3ByicH/XPZqy7Eougbs8OQQIoNW4xKw8PNyWf0lfr90qBfPj27INn6N7umVmbHCNCKkQ4frPn46xesw1ywtc2GhOEzZlC8ajlnzBUkj5FJZcrNjXfFmfsQcFQP0g/o/3CAUpk1BXFXt7eZsaYdyn0m7fMoyFt1wlF8egQeGYYE98vtKsvrII51HK8vOEf+5VXU4UZxGfvyzS3A8kuNEkKEh1n9mazjfPBT0KGSiOGh7Nugks+jjfswSgXRK/b2eP3fS7U625rbS798pKxnoS2E0Pgpzdk5fWoNgAlG/n2F9oI2/kQIDAQAB",
		PublicKeyDataType:  gocrypt.Base64,
		PrivateKey:         "MIIEowIBAAKCAQEAyoiAraTnAbCoqGVOKugFDM2/ms2szXmb3zTOU3ByicH/XPZqy7Eougbs8OQQIoNW4xKw8PNyWf0lfr90qBfPj27INn6N7umVmbHCNCKkQ4frPn46xesw1ywtc2GhOEzZlC8ajlnzBUkj5FJZcrNjXfFmfsQcFQP0g/o/3CAUpk1BXFXt7eZsaYdyn0m7fMoyFt1wlF8egQeGYYE98vtKsvrII51HK8vOEf+5VXU4UZxGfvyzS3A8kuNEkKEh1n9mazjfPBT0KGSiOGh7Nugks+jjfswSgXRK/b2eP3fS7U625rbS798pKxnoS2E0Pgpzdk5fWoNgAlG/n2F9oI2/kQIDAQABAoIBAF378hqiR0CVhe5+9EMc4BsM7zka8HF5WUe+7W/y4nPivmmZP/29/DQ3OoSekI4zfIJrDgkCL7JqspeaqLvIMN1Sfz4qhBq18mIcBw7CdI+R5yxcz1FAzq1LJtxAFdxWbTFCmoQsYYW2Zx1wyWlcrWPOvc1dm9p0t2b3HeM8T9jLdY+D0Bm9zmAS0nwTuDBxYS77DB9Ncl6pWLLd197/5IoN1/nunFuzpkiwMPI9RF7lgrnUthc/1Gfnylz5/tXCiQsEVSbAdbMXt9nsV0RgVeMcPq/aUqTMLS2lIV8JySWDrRQi4yPHU0hIjcp6ggo53YMuncJZweI/wwkJexojz0ECgYEA5QzRObpU0CryfJ7qa97/USIKHbvl6PuQG9OLyUeP9bG0edidQhUrR4EZwjIl73O8CTJ0bB24wAKZZEOK3eJeqG/N0q+CiD83ygr8pSZzpE1xvqQp32IgXtgvm7/UmT8cfAp05Z3bF4jcA8uXwodBz4NsVGijlO78PsCooLsArM0CgYEA4lz5pXDEN3w5JwkbspLnUSUS738hne8YM0PchCaww+8sXLS9GLL2CHcvwh6Tv9Mee7r6SdbDI73x118y68WEDDhidiYZCLhXJN2v12ezJOMqH5m9wVJzQOGNv6kPV1EW1WlWxoJQGxCdzbZMLxtTbyTZe3+iAVG++8u6NWMV3dUCgYA1dm1rnQto321kGy+6Z/2OMXTNBeufGwDDDfilzZdTkNwASMhEAW7trLuXcV8bahcsymMUTUevQawOFBnYupq/lAEluSOtq5vZBAF+huAdLJptFiJT6rKFkM5j+z2jW3DJnyMz6UmXT7GTDTVqCWoaBqIFfbsY60NjXlK92YhJzQKBgQDWfQjktbSHasLw9RV0oPRklD+cBhfBgfOpZ+0En3CxR+j+MxhW1gSBQwZS5wxTIGXrEeHlo4UmUe5diExE0dRsi+ToVPM1qw6P1SuwbQd3tXSNmu0NyOWCnfblm/j4YNLFB1p9IK9s5dLRQKJxpG/ribw15FuK6n2QM5vOyIPIvQKBgE5PUzRUCCVsjKAxZOfaZQatMbSzAUSB3bNmUw+F3pDq8ibs6XXvtySowG2femlPDNL7mDMuUc9kYrtTFTQNrEsQGB55wBopX3UxzRjpXJoAQ/d+RPdrSJC7xJyu+URoFI6ae0I3bx1BzjctYU0Rv5DUh+j9leMH5N2S9vHb+vqu",
		PrivateKeyType:     gocrypt.PKCS1,
		PrivateKeyDataType: gocrypt.Base64,
	}

2.構造handle

handle, err := gocrypt.NewCrypt(gocrypt.RSA, secretInfo)
	if err != nil {
		fmt.Println("new error :", err)
		return
	}

3.加密、解密、簽名、驗籤

(1)加密

加密指定字符串,並以指定編碼格式輸出結果

encrypt, err := handle.Encrypt("test", gocrypt.HEX)
	if err != nil {
		fmt.Println("encrypt error :", err)
		return
	}
	fmt.Println("encrypt data :", encrypt)

(2)解密

解密指定格式編碼後的加密串,返回原字符串

	decrypt, err := handle.Decrypt(encrypt, gocrypt.HEX)
	if err != nil {
		fmt.Println("decrypt error :", err)
		return
	}
	fmt.Println("decrypt data :", decrypt)

(3)簽名

以指定摘要算法簽名,並以指定編碼格式輸出結果

	sign, err := handle.Sign("test", gocrypt.SHA256, gocrypt.HEX)
	if err != nil {
		fmt.Println("sign error :", err)
		return
	}
	fmt.Println("sign data :", sign)

(4)驗籤

驗證字符串是否是以指定摘要算法編碼的簽名串的原始字符串

	verifySign, err := handle.VerifySign("test", gocrypt.SHA256, sign, gocrypt.HEX)
	if err != nil {
		fmt.Println("verifySign error :", err)
		return
	}
	fmt.Println("verifySign result :", verifySign)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章