github.com/PandaGoAdmin/utils@v0.0.0-20211208134815-d5461603a00f/encrypt.go (about)

     1  package kgo
     2  
     3  import (
     4  	"bytes"
     5  	"crypto"
     6  	"crypto/aes"
     7  	"crypto/cipher"
     8  	"crypto/hmac"
     9  	"crypto/rand"
    10  	"crypto/rsa"
    11  	"crypto/sha1"
    12  	"crypto/sha256"
    13  	"crypto/sha512"
    14  	"crypto/x509"
    15  	"encoding/base64"
    16  	"encoding/hex"
    17  	"encoding/pem"
    18  	"errors"
    19  	"fmt"
    20  	"golang.org/x/crypto/bcrypt"
    21  	"hash"
    22  	"io"
    23  	"math/big"
    24  	"strconv"
    25  	"time"
    26  )
    27  
    28  // Base64Encode 使用 MIME base64 对数据进行编码.
    29  func (ke *LkkEncrypt) Base64Encode(str []byte) []byte {
    30  	l := len(str)
    31  	if l > 0 {
    32  		buf := make([]byte, base64.StdEncoding.EncodedLen(l))
    33  		base64.StdEncoding.Encode(buf, str)
    34  		return buf
    35  	}
    36  
    37  	return nil
    38  }
    39  
    40  // Base64Decode 对使用 MIME base64 编码的数据进行解码.
    41  func (ke *LkkEncrypt) Base64Decode(str []byte) ([]byte, error) {
    42  	l := len(str)
    43  	if l > 0 {
    44  		dbuf := make([]byte, base64.StdEncoding.DecodedLen(l))
    45  		n, err := base64.StdEncoding.Decode(dbuf, str)
    46  		return dbuf[:n], err
    47  	}
    48  
    49  	return nil, nil
    50  }
    51  
    52  // Base64UrlSafeEncode url安全的Base64Encode,没有'/'和'+'及结尾的'=' .
    53  func (ke *LkkEncrypt) Base64UrlEncode(str []byte) []byte {
    54  	l := len(str)
    55  	if l > 0 {
    56  		buf := make([]byte, base64.StdEncoding.EncodedLen(l))
    57  		base64.StdEncoding.Encode(buf, str)
    58  
    59  		// Base64 Url Safe is the same as Base64 but does not contain '/' and '+' (replaced by '_' and '-') and trailing '=' are removed.
    60  		buf = bytes.Replace(buf, bytSlash, bytUnderscore, -1)
    61  		buf = bytes.Replace(buf, bytPlus, bytMinus, -1)
    62  		buf = bytes.Replace(buf, bytEqual, bytEmp, -1)
    63  
    64  		return buf
    65  	}
    66  
    67  	return nil
    68  }
    69  
    70  // Base64UrlDecode url安全的Base64Decode.
    71  func (ke *LkkEncrypt) Base64UrlDecode(str []byte) ([]byte, error) {
    72  	l := len(str)
    73  	if l > 0 {
    74  		var missing = (4 - len(str)%4) % 4
    75  		str = append(str, bytes.Repeat(bytEqual, missing)...)
    76  
    77  		dbuf := make([]byte, base64.URLEncoding.DecodedLen(len(str)))
    78  		n, err := base64.URLEncoding.Decode(dbuf, str)
    79  		return dbuf[:n], err
    80  	}
    81  
    82  	return nil, nil
    83  }
    84  
    85  // AuthCode 授权码编码或解码;encode为true时编码,为false解码;expiry为有效期,秒;返回结果为加密/解密的字符串和有效期时间戳.
    86  func (ke *LkkEncrypt) AuthCode(str, key []byte, encode bool, expiry int64) ([]byte, int64) {
    87  	// DYNAMIC_KEY_LEN 动态密钥长度,相同的明文会生成不同密文就是依靠动态密钥
    88  	// 加入随机密钥,可以令密文无任何规律,即便是原文和密钥完全相同,加密结果也会每次不同,增大破解难度。
    89  	// 取值越大,密文变动规律越大,密文变化 = 16 的 DYNAMIC_KEY_LEN 次方
    90  	// 当此值为 0 时,则不产生随机密钥
    91  
    92  	strLen := len(str)
    93  	if str == nil || strLen == 0 {
    94  		return nil, 0
    95  	} else if !encode && strLen < DYNAMIC_KEY_LEN {
    96  		return nil, 0
    97  	}
    98  
    99  	// 密钥
   100  	keyByte := md5Byte(key, 32)
   101  
   102  	// 密钥a会参与加解密
   103  	keya := keyByte[:16]
   104  
   105  	// 密钥b会用来做数据完整性验证
   106  	keyb := make([]byte, 16)
   107  	copy(keyb, keyByte[16:])
   108  
   109  	// 密钥c用于变化生成的密文
   110  	var keyc []byte
   111  	if encode == false {
   112  		keyc = str[:DYNAMIC_KEY_LEN]
   113  	} else {
   114  		now, _ := time.Now().MarshalBinary()
   115  		keycLen := 32 - DYNAMIC_KEY_LEN
   116  		timeBytes := md5Byte(now, 32)
   117  		keyc = timeBytes[keycLen:]
   118  	}
   119  
   120  	// 参与运算的密钥
   121  	keyd := md5Byte(append(keya, keyc...), 32)
   122  	cryptkey := append(keya, keyd...)
   123  	cryptkeyLen := len(cryptkey)
   124  	// 明文,前10位用来保存时间戳,解密时验证数据有效性,10到26位用来保存keyb(密钥b),解密时会通过这个密钥验证数据完整性
   125  	// 如果是解码的话,会从第 DYNAMIC_KEY_LEN 位开始,因为密文前 DYNAMIC_KEY_LEN 位保存 动态密钥,以保证解密正确
   126  	if encode == false { //解密
   127  		var err error
   128  		str, err = ke.Base64UrlDecode(str[DYNAMIC_KEY_LEN:])
   129  		if err != nil {
   130  			return nil, 0
   131  		}
   132  	} else {
   133  		if expiry != 0 {
   134  			expiry = expiry + time.Now().Unix()
   135  		}
   136  		expMd5 := md5Byte(append(str, keyb...), 16)
   137  		str = []byte(fmt.Sprintf("%010d%s%s", expiry, expMd5, str))
   138  	}
   139  
   140  	strLen = len(str)
   141  	resdata := make([]byte, 0, strLen)
   142  	var rndkey, box [256]int
   143  	// 产生密钥簿
   144  	h := 0
   145  	i := 0
   146  	j := 0
   147  
   148  	for i = 0; i < 256; i++ {
   149  		rndkey[i] = int(cryptkey[i%cryptkeyLen])
   150  		box[i] = i
   151  	}
   152  	// 用固定的算法,打乱密钥簿,增加随机性,好像很复杂,实际上并不会增加密文的强度
   153  	for i = 0; i < 256; i++ {
   154  		j = (j + box[i] + rndkey[i]) % 256
   155  		box[i], box[j] = box[j], box[i]
   156  	}
   157  	// 核心加解密部分
   158  	h = 0
   159  	j = 0
   160  	for i = 0; i < strLen; i++ {
   161  		h = ((h + 1) % 256)
   162  		j = ((j + box[h]) % 256)
   163  		box[h], box[j] = box[j], box[h]
   164  		// 从密钥簿得出密钥进行异或,再转成字符
   165  		resdata = append(resdata, byte(int(str[i])^box[(box[h]+box[j])%256]))
   166  	}
   167  	if encode == false { //解密
   168  		// substr($result, 0, 10) == 0 验证数据有效性
   169  		// substr($result, 0, 10) - time() > 0 验证数据有效性
   170  		// substr($result, 10, 16) == substr(md5(substr($result, 26).$keyb), 0, 16) 验证数据完整性
   171  		// 验证数据有效性,请看未加密明文的格式
   172  		if len(resdata) <= 26 {
   173  			return nil, 0
   174  		}
   175  
   176  		expTime, _ := strconv.ParseInt(string(resdata[:10]), 10, 0)
   177  		if (expTime == 0 || expTime-time.Now().Unix() > 0) && string(resdata[10:26]) == string(md5Byte(append(resdata[26:], keyb...), 16)) {
   178  			return resdata[26:], expTime
   179  		} else {
   180  			return nil, expTime
   181  		}
   182  	} else { //加密
   183  		// 把动态密钥保存在密文里,这也是为什么同样的明文,生产不同密文后能解密的原因
   184  		resdata = append(keyc, ke.Base64UrlEncode(resdata)...)
   185  		return resdata, expiry
   186  	}
   187  }
   188  
   189  // PasswordHash 创建密码的散列值;costs为算法的cost,范围4~31,默认10;注意:值越大越耗时.
   190  func (ke *LkkEncrypt) PasswordHash(password []byte, costs ...int) ([]byte, error) {
   191  	var cost int
   192  	if len(costs) == 0 {
   193  		cost = 10
   194  	} else {
   195  		cost = costs[0]
   196  		if cost < 4 {
   197  			cost = 4
   198  		} else if cost > 31 {
   199  			cost = 15
   200  		}
   201  	}
   202  
   203  	res, err := bcrypt.GenerateFromPassword(password, cost)
   204  	return res, err
   205  }
   206  
   207  // PasswordVerify 验证密码是否和散列值匹配.
   208  func (ke *LkkEncrypt) PasswordVerify(password, hash []byte) bool {
   209  	err := bcrypt.CompareHashAndPassword(hash, password)
   210  	return err == nil
   211  }
   212  
   213  // EasyEncrypt 简单加密.
   214  // data为要加密的原字符串,key为密钥.
   215  func (ke *LkkEncrypt) EasyEncrypt(data, key []byte) []byte {
   216  	dataLen := len(data)
   217  	if dataLen == 0 {
   218  		return nil
   219  	}
   220  
   221  	keyByte := md5Byte(key, 32)
   222  	keyLen := len(keyByte)
   223  
   224  	var i, x, c int
   225  	var res []byte
   226  	for i = 0; i < dataLen; i++ {
   227  		if x == keyLen {
   228  			x = 0
   229  		}
   230  
   231  		c = (int(data[i]) + int(keyByte[x])) % 256
   232  		res = append(res, byte(c))
   233  
   234  		x++
   235  	}
   236  
   237  	res = append(keyByte[:DYNAMIC_KEY_LEN], ke.Base64UrlEncode(res)...)
   238  	return res
   239  }
   240  
   241  // EasyDecrypt 简单解密.
   242  // val为待解密的字符串,key为密钥.
   243  func (ke *LkkEncrypt) EasyDecrypt(val, key []byte) []byte {
   244  	if len(val) <= DYNAMIC_KEY_LEN {
   245  		return nil
   246  	}
   247  
   248  	data, err := ke.Base64UrlDecode(val[DYNAMIC_KEY_LEN:])
   249  	if err != nil {
   250  		return nil
   251  	}
   252  
   253  	keyByte := md5Byte(key, 32)
   254  	if string(val[:DYNAMIC_KEY_LEN]) != string(keyByte[:DYNAMIC_KEY_LEN]) {
   255  		return nil
   256  	}
   257  
   258  	dataLen := len(data)
   259  	keyLen := len(keyByte)
   260  
   261  	var i, x, c int
   262  	var res []byte
   263  	for i = 0; i < dataLen; i++ {
   264  		if x == keyLen {
   265  			x = 0
   266  		}
   267  
   268  		if data[i] < keyByte[x] {
   269  			c = int(data[i]) + 256 - int(keyByte[x])
   270  		} else {
   271  			c = int(data[i]) - int(keyByte[x])
   272  		}
   273  		res = append(res, byte(c))
   274  
   275  		x++
   276  	}
   277  
   278  	return res
   279  }
   280  
   281  // HmacShaX HmacSHA-x加密,x为1/256/512 .
   282  func (ke *LkkEncrypt) HmacShaX(data, secret []byte, x uint16) []byte {
   283  	// Create a new HMAC by defining the hash type and the key (as byte array)
   284  	var h hash.Hash
   285  	switch x {
   286  	case 1:
   287  		h = hmac.New(sha1.New, secret)
   288  	case 256:
   289  		h = hmac.New(sha256.New, secret)
   290  	case 512:
   291  		h = hmac.New(sha512.New, secret)
   292  	default:
   293  		panic("[HmacShaX]`x must be in [1, 256, 512]")
   294  	}
   295  
   296  	// Write Data to it
   297  	h.Write(data)
   298  
   299  	src := h.Sum(nil)
   300  	dst := make([]byte, hex.EncodedLen(len(src)))
   301  	hex.Encode(dst, src)
   302  
   303  	return dst
   304  }
   305  
   306  // aesEncrypt AES加密.
   307  // clearText为明文;key为密钥,长度16/24/32;
   308  // mode为模式,枚举值(CBC,CFB,CTR,OFB);
   309  // paddingType为填充方式,枚举(PKCS_NONE,PKCS_ZERO,PKCS_SEVEN),默认PKCS_SEVEN.
   310  // 注意:返回的是一个字节切片指针.
   311  func (ke *LkkEncrypt) aesEncrypt(clearText, key []byte, mode string, paddingType ...LkkPKCSType) ([]byte, error) {
   312  	block, err := aes.NewCipher(key)
   313  	if err != nil {
   314  		return nil, err
   315  	}
   316  
   317  	pt := PKCS_SEVEN
   318  	blockSize := block.BlockSize()
   319  	if len(paddingType) > 0 {
   320  		pt = paddingType[0]
   321  	}
   322  
   323  	switch pt {
   324  	case PKCS_ZERO:
   325  		clearText = zeroPadding(clearText, blockSize)
   326  	case PKCS_SEVEN:
   327  		clearText = pkcs7Padding(clearText, blockSize, false)
   328  	}
   329  
   330  	//字节切片指针
   331  	cipherText := make([]byte, blockSize+len(clearText))
   332  	//初始化向量
   333  	iv := cipherText[:blockSize]
   334  	_, _ = io.ReadFull(rand.Reader, iv)
   335  
   336  	switch mode {
   337  	case "CBC":
   338  		cipher.NewCBCEncrypter(block, iv).CryptBlocks(cipherText[blockSize:], clearText)
   339  	case "CFB":
   340  		cipher.NewCFBEncrypter(block, iv).XORKeyStream(cipherText[blockSize:], clearText)
   341  	case "CTR":
   342  		cipher.NewCTR(block, iv).XORKeyStream(cipherText[blockSize:], clearText)
   343  	case "OFB":
   344  		cipher.NewOFB(block, iv).XORKeyStream(cipherText[blockSize:], clearText)
   345  	}
   346  
   347  	return cipherText, nil
   348  }
   349  
   350  // aesDecrypt AES解密.
   351  // cipherText为密文;key为密钥,长度16/24/32;
   352  // mode为模式,枚举值(CBC,CFB,CTR,OFB);
   353  // paddingType为填充方式,枚举(PKCS_NONE,PKCS_ZERO,PKCS_SEVEN),默认PKCS_SEVEN.
   354  func (ke *LkkEncrypt) aesDecrypt(cipherText, key []byte, mode string, paddingType ...LkkPKCSType) ([]byte, error) {
   355  	block, err := aes.NewCipher(key)
   356  	if err != nil {
   357  		return nil, err
   358  	}
   359  
   360  	pt := PKCS_SEVEN
   361  	if len(paddingType) > 0 {
   362  		pt = paddingType[0]
   363  	}
   364  
   365  	blockSize := block.BlockSize()
   366  	clen := len(cipherText)
   367  	if clen == 0 || clen < blockSize {
   368  		return nil, errors.New("[aesDecrypt]`cipherText too short")
   369  	}
   370  
   371  	iv := cipherText[:blockSize]
   372  	cipherText = cipherText[blockSize:]
   373  	originData := make([]byte, clen-blockSize)
   374  	switch mode {
   375  	case "CBC":
   376  		cipher.NewCBCDecrypter(block, iv).CryptBlocks(originData, cipherText)
   377  	case "CFB":
   378  		cipher.NewCFBDecrypter(block, iv).XORKeyStream(originData, cipherText)
   379  	case "CTR":
   380  		cipher.NewCTR(block, iv).XORKeyStream(originData, cipherText)
   381  	case "OFB":
   382  		cipher.NewOFB(block, iv).XORKeyStream(originData, cipherText)
   383  	}
   384  
   385  	clen = len(originData)
   386  	if pt != PKCS_NONE && clen > 0 && int(originData[clen-1]) > clen {
   387  		return nil, errors.New(fmt.Sprintf("[aesDecrypt] [%s] decrypt failed", mode))
   388  	}
   389  
   390  	var plainText []byte
   391  	switch pt {
   392  	case PKCS_ZERO:
   393  		plainText = zeroUnPadding(originData)
   394  	case PKCS_SEVEN:
   395  		plainText = pkcs7UnPadding(originData, blockSize)
   396  	default: //case PKCS_NONE
   397  		plainText = originData
   398  	}
   399  
   400  	return plainText, nil
   401  }
   402  
   403  // AesCBCEncrypt AES-CBC密码分组链接(Cipher-block chaining)模式加密.加密无法并行,不适合对流数据加密.
   404  // clearText为明文;key为密钥,长16/24/32;paddingType为填充方式,枚举(PKCS_ZERO,PKCS_SEVEN),默认PKCS_SEVEN.
   405  func (ke *LkkEncrypt) AesCBCEncrypt(clearText, key []byte, paddingType ...LkkPKCSType) ([]byte, error) {
   406  	return ke.aesEncrypt(clearText, key, "CBC", paddingType...)
   407  }
   408  
   409  // AesCBCDecrypt AES-CBC密码分组链接(Cipher-block chaining)模式解密.
   410  // cipherText为密文;key为密钥,长16/24/32;paddingType为填充方式,枚举(PKCS_NONE,PKCS_ZERO,PKCS_SEVEN),默认PKCS_SEVEN.
   411  func (ke *LkkEncrypt) AesCBCDecrypt(cipherText, key []byte, paddingType ...LkkPKCSType) ([]byte, error) {
   412  	return ke.aesDecrypt(cipherText, key, "CBC", paddingType...)
   413  }
   414  
   415  // AesCFBEncrypt AES-CFB密文反馈(Cipher feedback)模式加密.适合对流数据加密.
   416  // clearText为明文;key为密钥,长16/24/32.
   417  func (ke *LkkEncrypt) AesCFBEncrypt(clearText, key []byte) ([]byte, error) {
   418  	return ke.aesEncrypt(clearText, key, "CFB", PKCS_NONE)
   419  }
   420  
   421  // AesCFBDecrypt AES-CFB密文反馈(Cipher feedback)模式解密.
   422  // cipherText为密文;key为密钥,长16/24/32.
   423  func (ke *LkkEncrypt) AesCFBDecrypt(cipherText, key []byte) ([]byte, error) {
   424  	return ke.aesDecrypt(cipherText, key, "CFB", PKCS_NONE)
   425  }
   426  
   427  // AesCTREncrypt AES-CTR计算器(Counter)模式加密.
   428  // clearText为明文;key为密钥,长16/24/32.
   429  func (ke *LkkEncrypt) AesCTREncrypt(clearText, key []byte) ([]byte, error) {
   430  	return ke.aesEncrypt(clearText, key, "CTR", PKCS_NONE)
   431  }
   432  
   433  // AesCTRDecrypt AES-CTR计算器(Counter)模式解密.
   434  // cipherText为密文;key为密钥,长16/24/32.
   435  func (ke *LkkEncrypt) AesCTRDecrypt(cipherText, key []byte) ([]byte, error) {
   436  	return ke.aesDecrypt(cipherText, key, "CTR", PKCS_NONE)
   437  }
   438  
   439  // AesOFBEncrypt AES-OFB输出反馈(Output feedback)模式加密.适合对流数据加密.
   440  // clearText为明文;key为密钥,长16/24/32.
   441  func (ke *LkkEncrypt) AesOFBEncrypt(clearText, key []byte) ([]byte, error) {
   442  	return ke.aesEncrypt(clearText, key, "OFB", PKCS_NONE)
   443  }
   444  
   445  // AesOFBDecrypt AES-OFB输出反馈(Output feedback)模式解密.
   446  // cipherText为密文;key为密钥,长16/24/32.
   447  func (ke *LkkEncrypt) AesOFBDecrypt(cipherText, key []byte) ([]byte, error) {
   448  	return ke.aesDecrypt(cipherText, key, "OFB", PKCS_NONE)
   449  }
   450  
   451  // GenerateRsaKeys 生成RSA密钥对.bits为密钥位数,通常为1024或2048.
   452  func (ke *LkkEncrypt) GenerateRsaKeys(bits int) (private []byte, public []byte, err error) {
   453  	// 生成私钥文件
   454  	var privateKey *rsa.PrivateKey
   455  	privateKey, err = rsa.GenerateKey(rand.Reader, bits)
   456  	if err != nil {
   457  		return
   458  	}
   459  	derStream := x509.MarshalPKCS1PrivateKey(privateKey)
   460  	block := &pem.Block{
   461  		Type:  "RSA PRIVATE KEY",
   462  		Bytes: derStream,
   463  	}
   464  	privateBuff := new(bytes.Buffer)
   465  	_ = pem.Encode(privateBuff, block)
   466  
   467  	// 生成公钥文件
   468  	var derPkix []byte
   469  	publicKey := &privateKey.PublicKey
   470  	derPkix, _ = x509.MarshalPKIXPublicKey(publicKey)
   471  	block = &pem.Block{
   472  		Type:  "RSA PUBLIC KEY",
   473  		Bytes: derPkix,
   474  	}
   475  	publicBuff := new(bytes.Buffer)
   476  	_ = pem.Encode(publicBuff, block)
   477  
   478  	private = privateBuff.Bytes()
   479  	public = publicBuff.Bytes()
   480  
   481  	return
   482  }
   483  
   484  // RsaPublicEncrypt RSA公钥加密.
   485  // clearText为明文,publicKey为公钥.
   486  func (ke *LkkEncrypt) RsaPublicEncrypt(clearText, publicKey []byte) ([]byte, error) {
   487  	// 解密pem格式的公钥
   488  	block, _ := pem.Decode(publicKey)
   489  	if block == nil {
   490  		return nil, errors.New("[RsaPublicEncrypt]`public key error")
   491  	}
   492  
   493  	// 解析公钥
   494  	pubInterface, err := x509.ParsePKIXPublicKey(block.Bytes)
   495  	if err != nil {
   496  		return nil, err
   497  	}
   498  
   499  	// 类型断言
   500  	pubKey := pubInterface.(*rsa.PublicKey)
   501  	//加密
   502  	return rsa.EncryptPKCS1v15(rand.Reader, pubKey, clearText)
   503  }
   504  
   505  // RsaPrivateDecrypt RSA私钥解密.比加密耗时.
   506  // cipherText为密文,privateKey为私钥.
   507  func (ke *LkkEncrypt) RsaPrivateDecrypt(cipherText, privateKey []byte) ([]byte, error) {
   508  	// 获取私钥
   509  	block, _ := pem.Decode(privateKey)
   510  	if block == nil {
   511  		return nil, errors.New("[RsaPrivateDecrypt]`private key error!")
   512  	}
   513  
   514  	// 解析PKCS1格式的私钥
   515  	priv, err := x509.ParsePKCS1PrivateKey(block.Bytes)
   516  	if err != nil {
   517  		return nil, err
   518  	}
   519  
   520  	// 解密
   521  	return rsa.DecryptPKCS1v15(rand.Reader, priv, cipherText)
   522  }
   523  
   524  // RsaPrivateEncrypt RSA私钥加密.比解密耗时.
   525  // clearText为明文,privateKey为私钥.
   526  func (ke *LkkEncrypt) RsaPrivateEncrypt(clearText, privateKey []byte) ([]byte, error) {
   527  	// 获取私钥
   528  	block, _ := pem.Decode(privateKey)
   529  	if block == nil {
   530  		return nil, errors.New("[RsaPrivateEncrypt]`private key error!")
   531  	}
   532  
   533  	// 解析PKCS1格式的私钥
   534  	priv, err := x509.ParsePKCS1PrivateKey(block.Bytes)
   535  	if err != nil {
   536  		return nil, err
   537  	}
   538  
   539  	return rsa.SignPKCS1v15(nil, priv, crypto.Hash(0), clearText)
   540  }
   541  
   542  // RsaPublicDecrypt RSA公钥解密.
   543  // cipherText为密文,publicKey为公钥.
   544  func (ke *LkkEncrypt) RsaPublicDecrypt(cipherText, publicKey []byte) ([]byte, error) {
   545  	// 解密pem格式的公钥
   546  	block, _ := pem.Decode(publicKey)
   547  	if block == nil {
   548  		return nil, errors.New("[RsaPublicDecrypt]`public key error")
   549  	}
   550  
   551  	// 解析公钥
   552  	pubInterface, err := x509.ParsePKIXPublicKey(block.Bytes)
   553  	if err != nil {
   554  		return nil, err
   555  	}
   556  
   557  	// 类型断言
   558  	pubKey := pubInterface.(*rsa.PublicKey)
   559  
   560  	c := new(big.Int)
   561  	m := new(big.Int)
   562  	m.SetBytes(cipherText)
   563  	e := big.NewInt(int64(pubKey.E))
   564  	c.Exp(m, e, pubKey.N)
   565  	out := c.Bytes()
   566  	olen := len(out)
   567  	skip := 0
   568  	for i := 2; i < olen; i++ {
   569  		if (i+1 < olen) && out[i] == 0xff && out[i+1] == 0 {
   570  			skip = i + 2
   571  			break
   572  		}
   573  	}
   574  
   575  	return out[skip:], nil
   576  }