//EncryptRSA encrypt given data with RSA algorithm
func EncryptRSA(data []byte) []byte {
	if data == nil {
		return nil
	}
	publicKey := []byte(PublicKey)
	if !ginutil.IsProduction() {
		publicKey = []byte(TestPublicKey)
	}
	block, _ := pem.Decode(publicKey)
	if block == nil {
		return nil
	}
	pubInterface, err := x509.ParsePKIXPublicKey(block.Bytes)
	if err != nil {
		return nil
	}
	pub := pubInterface.(*rsa.PublicKey)
	encrypted := make([]byte, 0, len(data))
	for i := 0; i < len(data); i += 117 {
		if i+117 < len(data) {
			partial, err1 := rsa.EncryptPKCS1v15(rand.Reader, pub, data[i:i+117])
			if err1 != nil {
				return nil
			}
			encrypted = append(encrypted, partial...)
		} else {
			partial, err1 := rsa.EncryptPKCS1v15(rand.Reader, pub, data[i:])
			if err1 != nil {
				return nil
			}
			encrypted = append(encrypted, partial...)
		}
	}
	return encrypted
}
//SignWithRSA sign given encrypted data with RSA algorithm
func SignRSA(raw []byte, algorithm crypto.Hash) []byte {
	if raw == nil {
		return nil
	}
	privateKey := []byte(PrivateKey)
	if !ginutil.IsProduction() {
		privateKey = []byte(TestPrivateKey)
	}
	block, _ := pem.Decode(privateKey)
	if block == nil {
		return nil
	}
	privInterface, err := x509.ParsePKCS8PrivateKey(block.Bytes)
	if err != nil {
		return nil
	}
	priv := privInterface.(*rsa.PrivateKey)
	var data []byte
	if algorithm == crypto.SHA1 {
		data = EncryptSHA(raw)
	} else {
		data = EncryptMD5(EncryptSHA(raw))
	}
	signed, err := rsa.SignPKCS1v15(rand.Reader, priv, algorithm, data)
	if err != nil {
		return nil
	}
	return signed
}
//VerifySignature verify whether the given signature is correct
func VerifySignature(raw []byte, signature string, algorithm crypto.Hash) bool {
	if raw == nil || signature == "" {
		return false
	}
	publicKey := []byte(PublicKey)
	if !ginutil.IsProduction() {
		publicKey = []byte(TestPublicKey)
	}
	block, _ := pem.Decode(publicKey)
	if block == nil {
		return false
	}
	pubInterface, err := x509.ParsePKIXPublicKey(block.Bytes)
	if err != nil {
		return false
	}
	pub := pubInterface.(*rsa.PublicKey)
	var data []byte
	if algorithm == crypto.SHA1 {
		data = EncryptSHA(raw)
	} else {
		data = EncryptMD5(EncryptSHA(raw))
	}
	err = rsa.VerifyPKCS1v15(pub, algorithm, data, DecryptBase64(signature))
	if err != nil {
		return false
	}
	return true
}
//DecryptRSA decrypt given []byte with RSA algorithm
func DecryptRSA(data []byte) []byte {
	if data == nil {
		return nil
	}
	privateKey := []byte(PrivateKey)
	if !ginutil.IsProduction() {
		privateKey = []byte(TestPrivateKey)
	}
	block, _ := pem.Decode(privateKey)
	if block == nil {
		return nil
	}
	privInterface, err := x509.ParsePKCS8PrivateKey(block.Bytes)
	if err != nil {
		return nil
	}
	priv := privInterface.(*rsa.PrivateKey)
	decrypted := make([]byte, 0, len(data))
	for i := 0; i < len(data); i += 128 {
		if i+128 < len(data) {
			partial, err1 := rsa.DecryptPKCS1v15(rand.Reader, priv, data[i:i+128])
			if err1 != nil {
				return nil
			}
			decrypted = append(decrypted, partial...)
		} else {
			partial, err1 := rsa.DecryptPKCS1v15(rand.Reader, priv, data[i:])
			if err1 != nil {
				return nil
			}
			decrypted = append(decrypted, partial...)
		}
	}
	return decrypted
}
//NewZMOpenApiClient return a new ZMOpenApiClient
func NewZMOpenApiClient() *ZMOpenAPIClient {
	client := &http.Client{
		Timeout: time.Duration(time.Second * 3),
	}
	ret := &ZMOpenAPIClient{
		Host:       util.DefaultHost,
		AppID:      util.AppID,
		MerchantID: util.MerchantID,
		charset:    util.DefaultCharset,
		c:          client,
	}
	if !ginutil.IsProduction() {
		ret.AppID = util.TestAppID
		ret.MerchantID = util.TestMerchantID
	}
	return ret
}