我在golang中关于RSA加密、解密、签名、验签的总结一文中介绍了常见的一些使用情况,并做了一些针对性的方法实例。但鉴于实例中部分参数稍微变化则需要调整整个方法,本文则从通用的角度去处理这些差异点,正确在可设置的范围内实现通用的方法。
项目地址:gocrypt,欢迎star和fork。
RSA目前常用的就是加密、解密、签名、验签相关的内容,我们则从这4个方向去做通用的解决方案。以下是具体的情况总结,与前言中提到的文章有关
两者可以相互转化,PKCS8主要用于JAVA中,PKCS1用于其他语言中,当然golang中两种格式都可以使用
目前最常用的摘要算法方式如下:
如目前支付宝中:使用了RSA(SHA1)和RSA2(SHA256)两种签名算法,秘钥越长,摘要的长度越长,信息越安全。
目前最常用的信息编码格式如下:
我们针对方案说明中的情况均做了处理,作为可设置项。一下代码对应相应的设置项。
//私钥格式
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
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,
}
handle, err := gocrypt.NewCrypt(gocrypt.RSA, secretInfo)
if err != nil {
fmt.Println("new error :", err)
return
}
加密指定字符串,并以指定编码格式输出结果
encrypt, err := handle.Encrypt("test", gocrypt.HEX)
if err != nil {
fmt.Println("encrypt error :", err)
return
}
fmt.Println("encrypt data :", encrypt)
解密指定格式编码后的加密串,返回原字符串
decrypt, err := handle.Decrypt(encrypt, gocrypt.HEX)
if err != nil {
fmt.Println("decrypt error :", err)
return
}
fmt.Println("decrypt data :", decrypt)
以指定摘要算法签名,并以指定编码格式输出结果
sign, err := handle.Sign("test", gocrypt.SHA256, gocrypt.HEX)
if err != nil {
fmt.Println("sign error :", err)
return
}
fmt.Println("sign data :", sign)
验证字符串是否是以指定摘要算法编码的签名串的原始字符串
verifySign, err := handle.VerifySign("test", gocrypt.SHA256, sign, gocrypt.HEX)
if err != nil {
fmt.Println("verifySign error :", err)
return
}
fmt.Println("verifySign result :", verifySign)