diff --git a/README.md b/README.md index 4578fee..24d8afd 100644 --- a/README.md +++ b/README.md @@ -6,14 +6,18 @@ ![GitHub go.mod Go version (branch)](https://img.shields.io/github/go-mod/go-version/houseme/gocrypto/main) ## 特别说明 -based on https://github.com/farmerx/gorsa, https://github.com/yuchenfw/gocrypt Optimized the following points for packaging: + +based on https://github.com/farmerx/gorsa, https://github.com/yuchenfw/gocrypt Optimized the following points for +packaging: + - Optimization of public and private keys requires registration and initialization in advance. -- The encryption machine does not perform base64 processing, and avoids secondary encapsulation of base64 during cross-program transfer or storage +- The encryption machine does not perform base64 processing, and avoids secondary encapsulation of base64 during + cross-program transfer or storage - The incoming return uses the string type uniformly to avoid conversion trouble - Supports RSAWithSHA1 and RSAWithSHA256 signature verification algorithms -此版本新增了AES、DES、3DES、HMAC、HASH等常见加/解密及hash获取方式,结构作了些调整,由之前的版本更新到此版本时一定要注意引用方法包名的变化。 -AES/DES块加密时,填充默认采用PKCS7 padding(如果块大小为64 位(8字节)时,此时PKCS7与PKCS5结果一致). +此版本新增了AES、DES、3DES、HMAC、HASH等常见加/解密及hash获取方式,结构作了些调整,由之前的版本更新到此版本时一定要注意引用方法包名的变化。 AES/DES块加密时,填充默认采用PKCS7 padding( +如果块大小为64 位(8字节)时,此时PKCS7与PKCS5结果一致). ## get & import @@ -26,12 +30,12 @@ go get -u -v github.com/houseme/gocrypto ### 1.构建需要加解密的类型handle ```go -handleRSA := rsa.NewRSACrypt(secretInfo)//RSA -handleDES := des.NewDESCrypt(key)//des -handle3DES := des.NewTripleDESCrypt(key)//3des -handleAES := aes.NewAESCrypt(key)//aes -handleHash := hash.NewHash(hashType)//common hash -handleHMAC := hash.NewHMAC(hashType,key)//hmac + handleRSA := rsa.NewRSACrypt(secretInfo) // RSA + handleDES := des.NewDESCrypt(key) // des + handle3DES := des.NewTripleDESCrypt(key) // 3des + handleAES := aes.NewAESCrypt(key) // aes + handleHash := hash.NewHash(hashType) // common hash + handleHMAC := hash.NewHMAC(hashType, key) // hmac ``` ### 2.加密、解密、hash、hmac @@ -41,7 +45,7 @@ handleHMAC := hash.NewHMAC(hashType,key)//hmac 加密指定字符串,并以指定编码格式输出结果 ```go -encrypt, err := handle.Encrypt(src)//des/3des/aes + encrypt, err := handle.Encrypt(src) // des/3des/aes ``` #### (2)解密 @@ -49,7 +53,7 @@ encrypt, err := handle.Encrypt(src)//des/3des/aes 解密指定格式编码后的加密串,返回原字符串 ```go -decrypt, err := handle.Decrypt(src)//des/3des/aes + decrypt, err := handle.Decrypt(src) // des/3des/aes ``` #### (3)hash/hmac @@ -57,8 +61,8 @@ decrypt, err := handle.Decrypt(src)//des/3des/aes 哈希运算/密钥相关的哈希运算。 ```go - handle.Get([]byte("123456"))//输出[]byte - handle.EncodeToString([]byte("123456"),gocrypt.HEX)//输出为hex格式的字符串 + handle.Get([]byte("123456"))// 输出[]byte + handle.EncodeToString([]byte("123456"), gocrypto.HEX) // 输出为hex格式的字符串 ``` ## RSA加密、解密、签名、验签 @@ -66,13 +70,13 @@ decrypt, err := handle.Decrypt(src)//des/3des/aes ### 1.设置公私钥信息 ```go - secretInfo := rsa.RSASecret{ - 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, - } +secretInfo := rsa.RSASecret{ + PublicKey: "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyoiAraTnAbCoqGVOKugFDM2/ms2szXmb3zTOU3ByicH/XPZqy7Eougbs8OQQIoNW4xKw8PNyWf0lfr90qBfPj27INn6N7umVmbHCNCKkQ4frPn46xesw1ywtc2GhOEzZlC8ajlnzBUkj5FJZcrNjXfFmfsQcFQP0g/o/3CAUpk1BXFXt7eZsaYdyn0m7fMoyFt1wlF8egQeGYYE98vtKsvrII51HK8vOEf+5VXU4UZxGfvyzS3A8kuNEkKEh1n9mazjfPBT0KGSiOGh7Nugks+jjfswSgXRK/b2eP3fS7U625rbS798pKxnoS2E0Pgpzdk5fWoNgAlG/n2F9oI2/kQIDAQAB", + PublicKeyDataType: gocrypto.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: gocrypto.PKCS1, + PrivateKeyDataType: gocrypto.Base64, +} ``` ### 加密、解密、签名、验签 @@ -82,12 +86,12 @@ decrypt, err := handle.Decrypt(src)//des/3des/aes 加密指定字符串,并以指定编码格式输出结果 ```go -encrypt, err := handle.Encrypt("test", gocrypt.HEX) - if err != nil { - fmt.Println("encrypt error :", err) - return - } - fmt.Println("encrypt data :", encrypt) +encrypt, err := handle.Encrypt("test", gocrypto.HEX) +if err != nil { + fmt.Println("encrypt error :", err) + return +} +fmt.Println("encrypt data :", encrypt) ``` #### (2)RSA解密 @@ -95,12 +99,12 @@ encrypt, err := handle.Encrypt("test", gocrypt.HEX) 解密指定格式编码后的加密串,返回原字符串 ```go - decrypt, err := handle.Decrypt(encrypt, gocrypt.HEX) - if err != nil { - fmt.Println("decrypt error :", err) - return - } - fmt.Println("decrypt data :", decrypt) +decrypt, err := handle.Decrypt(encrypt, gocrypto.HEX) +if err != nil { + fmt.Println("decrypt error :", err) + return +} +fmt.Println("decrypt data :", decrypt) ``` #### (3)RSA签名 @@ -108,12 +112,12 @@ encrypt, err := handle.Encrypt("test", gocrypt.HEX) 以指定摘要算法签名,并以指定编码格式输出结果,仅适用于RSA。 ```go - sign, err := handle.Sign("test", gocrypt.SHA256, gocrypt.HEX) - if err != nil { - fmt.Println("sign error :", err) - return - } - fmt.Println("sign data :", sign) +sign, err := handle.Sign("test", gocrypto.SHA256, gocrypto.HEX) +if err != nil { + fmt.Println("sign error :", err) + return +} +fmt.Println("sign data :", sign) ``` #### (4)RSA验签 @@ -121,10 +125,36 @@ encrypt, err := handle.Encrypt("test", gocrypt.HEX) 验证字符串是否是以指定摘要算法编码的签名串的原始字符串,仅适用于RSA。 ```go - verifySign, err := handle.VerifySign("test", gocrypt.SHA256, sign, gocrypt.HEX) - if err != nil { - fmt.Println("verifySign error :", err) - return - } - fmt.Println("verifySign result :", verifySign) +verifySign, err := handle.VerifySign("test", gocrypto.SHA256, sign, gocrypto.HEX) +if err != nil { + fmt.Println("verifySign error :", err) + return +} +fmt.Println("verifySign result :", verifySign) ``` + +#### (5)RSA私钥加密 + +加密指定字符串,并以指定编码格式输出结果 + +```go +encrypt, err := handle.EncryptByPriKey("test", gocrypto.HEX) +if err != nil { + fmt.Println("encrypt error :", err) + return +} +fmt.Println("encrypt data :", encrypt) +``` + +#### (6)RSA公钥解密 + +解密指定格式编码后的加密串,返回原字符串 + +```go +decrypt, err := handle.DecryptByPublic(encrypt, gocrypto.HEX) +if err != nil { + fmt.Println("decrypt error :", err) + return +} +fmt.Println("decrypt data :", decrypt) +``` \ No newline at end of file diff --git a/rsa/rsa.go b/rsa/rsa.go index 0182d8d..c569ec4 100644 --- a/rsa/rsa.go +++ b/rsa/rsa.go @@ -15,6 +15,7 @@ package rsa import ( + "bytes" "crypto/rand" "crypto/rsa" "crypto/x509" @@ -144,8 +145,67 @@ func (rc *rsaCrypt) VerifySign(src string, hashType gocrypto.Hash, signedData st return false, err } signDecoded, err := gocrypto.DecodeString(signedData, signDataType) + if err != nil { + return false, err + } if err = rsa.VerifyPKCS1v15(pubKey.(*rsa.PublicKey), cryptoHash, hashed, signDecoded); err != nil { return false, err } return true, nil } + +// EncryptByPriKey encrypts the given message with private key +// src the original data +// outputDataType the encode type of encrypted data ,such as Base64,HEX +func (rc *rsaCrypt) EncryptByPriKey(src string, outputDataType gocrypto.Encode) (dst string, err error) { + secretInfo := rc.secretInfo + if secretInfo.PrivateKey == "" { + return "", fmt.Errorf("secretInfo PrivateKey can't be empty") + } + privateKeyDecoded, err := gocrypto.DecodeString(secretInfo.PrivateKey, secretInfo.PrivateKeyDataType) + if err != nil { + return + } + prvKey, err := gocrypto.ParsePrivateKey(privateKeyDecoded, secretInfo.PrivateKeyType) + if err != nil { + return + } + + output := bytes.NewBuffer(nil) + err = priKeyIO(prvKey, bytes.NewReader([]byte(src)), output, true) + if err != nil { + return "", err + } + + return gocrypto.EncodeToString(output.Bytes(), outputDataType) +} + +// DecryptByPublic decrypts a plaintext using public key +// src the encrypted data with private key +// srcType the encode type of encrypted data ,such as Base64,HEX +func (rc *rsaCrypt) DecryptByPublic(src string, srcType gocrypto.Encode) (dst string, err error) { + secretInfo := rc.secretInfo + if secretInfo.PublicKey == "" { + return "", fmt.Errorf("secretInfo PublicKey can't be empty") + } + pubKeyDecoded, err := gocrypto.DecodeString(secretInfo.PublicKey, secretInfo.PublicKeyDataType) + if err != nil { + return + } + pubKey, err := x509.ParsePKIXPublicKey(pubKeyDecoded) + if err != nil { + return + } + + decodeData, err := gocrypto.DecodeString(src, srcType) + if err != nil { + return + } + + output := bytes.NewBuffer(nil) + err = pubKeyIO(pubKey.(*rsa.PublicKey), bytes.NewReader(decodeData), output, false) + if err != nil { + return "", err + } + return output.String(), nil +} diff --git a/rsa/rsa_ext.go b/rsa/rsa_ext.go new file mode 100644 index 0000000..7ee37ff --- /dev/null +++ b/rsa/rsa_ext.go @@ -0,0 +1,375 @@ +package rsa + +// @Project: gocrypto +// @Author: houseme +// @Description: +// @File: rsa_ext +// @Version: 1.0.0 +// @Date: 2021/8/10 15:24 +// @Package gorsa + +import ( + "bytes" + "crypto/rand" + "crypto/rsa" + "crypto/x509" + "errors" + "io" + "io/ioutil" + "math/big" + + "github.com/houseme/gocrypto" +) + +var ( + // ErrDataToLarge . + ErrDataToLarge = errors.New("message too long for RSA public key size") + // ErrDataLen . + ErrDataLen = errors.New("data length error") + // ErrDataBroken . + ErrDataBroken = errors.New("data broken, first byte is not zero") + // ErrKeyPairDisMatch . + ErrKeyPairDisMatch = errors.New("data is not encrypted by the private key") + // ErrDecryption . + ErrDecryption = errors.New("decryption error") + // ErrPublicKey . + ErrPublicKey = errors.New("get public key error") + // ErrPrivateKey . + ErrPrivateKey = errors.New("get private key error") +) + +// 设置公钥 +func getPubKey(publicKey string, pubType gocrypto.Encode) (*rsa.PublicKey, error) { + // decode public key + if publicKey == "" { + return nil, errors.New("secretInfo PublicKey can't be empty") + } + pubKeyDecoded, err := gocrypto.DecodeString(publicKey, pubType) + if err != nil { + return nil, err + } + // x509 parse public key + pub, err := x509.ParsePKIXPublicKey(pubKeyDecoded) + if err != nil { + return nil, err + } + return pub.(*rsa.PublicKey), err +} + +// 设置私钥 +func getPriKey(privateKey string, priType gocrypto.Encode, priKeyType gocrypto.Secret) (*rsa.PrivateKey, error) { + if privateKey == "" { + return nil, errors.New("PrivateKey can't be empty") + } + + privateKeyDecoded, err := gocrypto.DecodeString(privateKey, priType) + if err != nil { + return nil, err + } + + return gocrypto.ParsePrivateKey(privateKeyDecoded, priKeyType) +} + +// 公钥加密或解密byte +func pubKeyByte(pub *rsa.PublicKey, in []byte, isEncrypt bool) ([]byte, error) { + k := (pub.N.BitLen() + 7) / 8 + if isEncrypt { + k = k - 11 + } + if len(in) <= k { + if isEncrypt { + return rsa.EncryptPKCS1v15(rand.Reader, pub, in) + } + return pubKeyDecrypt(pub, in) + } + iv := make([]byte, k) + out := bytes.NewBuffer(iv) + if err := pubKeyIO(pub, bytes.NewReader(in), out, isEncrypt); err != nil { + return nil, err + } + return ioutil.ReadAll(out) + +} + +// 私钥加密或解密byte +func priKeyByte(pri *rsa.PrivateKey, in []byte, isEncrypt bool) ([]byte, error) { + k := (pri.N.BitLen() + 7) / 8 + if isEncrypt { + k = k - 11 + } + if len(in) <= k { + if isEncrypt { + return priKeyEncrypt(rand.Reader, pri, in) + } + return rsa.DecryptPKCS1v15(rand.Reader, pri, in) + } + iv := make([]byte, k) + out := bytes.NewBuffer(iv) + if err := priKeyIO(pri, bytes.NewReader(in), out, isEncrypt); err != nil { + return nil, err + } + return ioutil.ReadAll(out) +} + +// 公钥加密或解密Reader +func pubKeyIO(pub *rsa.PublicKey, in io.Reader, out io.Writer, isEncrypt bool) error { + k := (pub.N.BitLen() + 7) / 8 + if isEncrypt { + k = k - 11 + } + buf := make([]byte, k) + var ( + b []byte + err error + ) + size := 0 + for { + size, err = in.Read(buf) + if err != nil { + if err == io.EOF { + return nil + } + return err + } + if size < k { + b = buf[:size] + } else { + b = buf + } + if isEncrypt { + b, err = rsa.EncryptPKCS1v15(rand.Reader, pub, b) + } else { + b, err = pubKeyDecrypt(pub, b) + } + if err != nil { + return err + } + if _, err = out.Write(b); err != nil { + return err + } + } + return nil +} + +// 私钥加密或解密Reader +func priKeyIO(pri *rsa.PrivateKey, r io.Reader, w io.Writer, isEncrypt bool) error { + k := (pri.N.BitLen() + 7) / 8 + if isEncrypt { + k = k - 11 + } + buf := make([]byte, k) + var ( + b []byte + err error + ) + size := 0 + for { + size, err = r.Read(buf) + if err != nil { + if err == io.EOF { + return nil + } + return err + } + if size < k { + b = buf[:size] + } else { + b = buf + } + if isEncrypt { + b, err = priKeyEncrypt(rand.Reader, pri, b) + } else { + b, err = rsa.DecryptPKCS1v15(rand.Reader, pri, b) + } + if err != nil { + return err + } + if _, err = w.Write(b); err != nil { + return err + } + } + return nil +} + +// 公钥解密 +func pubKeyDecrypt(pub *rsa.PublicKey, data []byte) ([]byte, error) { + k := (pub.N.BitLen() + 7) / 8 + if k != len(data) { + return nil, ErrDataLen + } + m := new(big.Int).SetBytes(data) + if m.Cmp(pub.N) > 0 { + return nil, ErrDataToLarge + } + m.Exp(m, big.NewInt(int64(pub.E)), pub.N) + d := leftPad(m.Bytes(), k) + if d[0] != 0 { + return nil, ErrDataBroken + } + if d[1] != 0 && d[1] != 1 { + return nil, ErrKeyPairDisMatch + } + var i = 2 + for ; i < len(d); i++ { + if d[i] == 0 { + break + } + } + i++ + if i == len(d) { + return nil, nil + } + return d[i:], nil +} + +// 私钥加密 +func priKeyEncrypt(rand io.Reader, priv *rsa.PrivateKey, hashed []byte) ([]byte, error) { + tLen := len(hashed) + k := (priv.N.BitLen() + 7) / 8 + if k < tLen+11 { + return nil, ErrDataLen + } + em := make([]byte, k) + em[1] = 1 + for i := 2; i < k-tLen-1; i++ { + em[i] = 0xff + } + copy(em[k-tLen:k], hashed) + m := new(big.Int).SetBytes(em) + c, err := decrypt(rand, priv, m) + if err != nil { + return nil, err + } + copyWithLeftPad(em, c.Bytes()) + return em, nil +} + +// 从crypto/rsa复制 +var bigZero = big.NewInt(0) +var bigOne = big.NewInt(1) + +// 从crypto/rsa复制 +func encrypt(c *big.Int, pub *rsa.PublicKey, m *big.Int) *big.Int { + e := big.NewInt(int64(pub.E)) + c.Exp(m, e, pub.N) + return c +} + +// 从crypto/rsa复制 +func decrypt(random io.Reader, priv *rsa.PrivateKey, c *big.Int) (m *big.Int, err error) { + if c.Cmp(priv.N) > 0 { + err = ErrDecryption + return + } + var ir *big.Int + if random != nil { + var r *big.Int + + for { + r, err = rand.Int(random, priv.N) + if err != nil { + return + } + if r.Cmp(bigZero) == 0 { + r = bigOne + } + var ok bool + ir, ok = modInverse(r, priv.N) + if ok { + break + } + } + bigE := big.NewInt(int64(priv.E)) + rpowe := new(big.Int).Exp(r, bigE, priv.N) + cCopy := new(big.Int).Set(c) + cCopy.Mul(cCopy, rpowe) + cCopy.Mod(cCopy, priv.N) + c = cCopy + } + if priv.Precomputed.Dp == nil { + m = new(big.Int).Exp(c, priv.D, priv.N) + } else { + m = new(big.Int).Exp(c, priv.Precomputed.Dp, priv.Primes[0]) + m2 := new(big.Int).Exp(c, priv.Precomputed.Dq, priv.Primes[1]) + m.Sub(m, m2) + if m.Sign() < 0 { + m.Add(m, priv.Primes[0]) + } + m.Mul(m, priv.Precomputed.Qinv) + m.Mod(m, priv.Primes[0]) + m.Mul(m, priv.Primes[1]) + m.Add(m, m2) + + for i, values := range priv.Precomputed.CRTValues { + prime := priv.Primes[2+i] + m2.Exp(c, values.Exp, prime) + m2.Sub(m2, m) + m2.Mul(m2, values.Coeff) + m2.Mod(m2, prime) + if m2.Sign() < 0 { + m2.Add(m2, prime) + } + m2.Mul(m2, values.R) + m.Add(m, m2) + } + } + if ir != nil { + m.Mul(m, ir) + m.Mod(m, priv.N) + } + + return +} + +// 从crypto/rsa复制 +func copyWithLeftPad(dest, src []byte) { + numPaddingBytes := len(dest) - len(src) + for i := 0; i < numPaddingBytes; i++ { + dest[i] = 0 + } + copy(dest[numPaddingBytes:], src) +} + +// 从crypto/rsa复制 +func nonZeroRandomBytes(s []byte, rand io.Reader) (err error) { + _, err = io.ReadFull(rand, s) + if err != nil { + return + } + for i := 0; i < len(s); i++ { + for s[i] == 0 { + _, err = io.ReadFull(rand, s[i:i+1]) + if err != nil { + return + } + s[i] ^= 0x42 + } + } + return +} + +// 从crypto/rsa复制 +func leftPad(input []byte, size int) (out []byte) { + n := len(input) + if n > size { + n = size + } + out = make([]byte, size) + copy(out[len(out)-n:], input) + return +} + +// 从crypto/rsa复制 +func modInverse(a, n *big.Int) (ia *big.Int, ok bool) { + g := new(big.Int) + x := new(big.Int) + y := new(big.Int) + g.GCD(x, y, a, n) + if g.Cmp(bigOne) != 0 { + return + } + if x.Cmp(bigOne) < 0 { + x.Add(x, n) + } + return x, true +} diff --git a/rsa/rsa_test.go b/rsa/rsa_test.go index b6efa12..e096884 100644 --- a/rsa/rsa_test.go +++ b/rsa/rsa_test.go @@ -65,6 +65,17 @@ func TestRSACrypt(t *testing.T) { if !verifySign { t.Fatal("verifySign result failed") } + encrypt, err = handle.EncryptByPriKey(rsaTest.data, rsaTest.encodeType) + if err != nil { + t.Fatalf("encrypt error : %v", err) + } + decrypt, err = handle.DecryptByPublic(encrypt, rsaTest.encodeType) + if err != nil { + t.Fatalf("decrypt error : %v", err) + } + if decrypt != rsaTest.data { + t.Fatalf("decrypt get result %s , want get %s ", decrypt, rsaTest.data) + } } } @@ -122,6 +133,17 @@ func BenchmarkRSACrypt(t *testing.B) { if !verifySign { t.Fatal("verifySign result failed") } + encrypt, err = handle.EncryptByPriKey(rsaTest.data, rsaTest.encodeType) + if err != nil { + t.Fatalf("encrypt error : %v", err) + } + decrypt, err = handle.DecryptByPublic(encrypt, rsaTest.encodeType) + if err != nil { + t.Fatalf("decrypt error : %v", err) + } + if decrypt != rsaTest.data { + t.Fatalf("decrypt get result %s , want get %s ", decrypt, rsaTest.data) + } } } }