You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

285 lines
8.1 KiB

  1. package auth
  2. import (
  3. "crypto/rand"
  4. "crypto/rsa"
  5. "crypto/x509"
  6. "gitlab.ecloud.com/ecloud/ecloudsdkcore/consts"
  7. "gitlab.ecloud.com/ecloud/ecloudsdkcore/errs"
  8. "gitlab.ecloud.com/ecloud/ecloudsdkcore/request"
  9. "gitlab.ecloud.com/ecloud/ecloudsdkcore/utils"
  10. "net/url"
  11. "sort"
  12. "strings"
  13. "time"
  14. )
  15. type ICredential interface {
  16. Sign(request *request.HttpRequest, credential *Credential) error
  17. Encrypt(data []byte, publicKey string) (string, error)
  18. Decrypt(originStr string, privateKey string) (string, error)
  19. }
  20. type MopCredential struct {
  21. }
  22. type NoneCredential struct {
  23. }
  24. type AKSKCredential struct {
  25. }
  26. func NewMopCredential() *MopCredential {
  27. return &MopCredential{}
  28. }
  29. func NewAKSKCredential() *AKSKCredential {
  30. return &AKSKCredential{}
  31. }
  32. func NewNoneCredential() *NoneCredential {
  33. return &NoneCredential{}
  34. }
  35. var MopCredentialInstance = NewMopCredential()
  36. var NoneCredentialInstance = NewNoneCredential()
  37. var AKSKCredentialInstance = NewAKSKCredential()
  38. func GetCredentialManager(credType CredentialType) ICredential {
  39. switch credType {
  40. case CredentialAkSk:
  41. return AKSKCredentialInstance
  42. case CredentialMop:
  43. return MopCredentialInstance
  44. case CredentialNone:
  45. return NoneCredentialInstance
  46. default:
  47. return AKSKCredentialInstance
  48. }
  49. }
  50. func (none *NoneCredential) Sign(request *request.HttpRequest, credential *Credential) error {
  51. request.BuildQueryParamsString()
  52. return nil
  53. }
  54. func (none *NoneCredential) Encrypt(data []byte, publicKey string) (string, error) {
  55. return string(data), nil
  56. }
  57. func (none *NoneCredential) Decrypt(originStr string, privateKey string) (string, error) {
  58. return originStr, nil
  59. }
  60. func (mop *MopCredential) Sign(request *request.HttpRequest, credential *Credential) error {
  61. if utils.IsUnSet(credential.PrivateKey) {
  62. return errs.NewInvalidParameterError("RSA private key can not be null", nil)
  63. }
  64. request.ConvertQueryParamsFromPath()
  65. parameters := make(map[string]string)
  66. for k, v := range request.QueryParams {
  67. if utils.IsSet(k) {
  68. parameters[k] = v
  69. }
  70. }
  71. flowdId := utils.Nonce()
  72. parameters["flowdId"] = flowdId
  73. keys := make([]string, len(parameters))
  74. index := 0
  75. for key := range parameters {
  76. keys[index] = key
  77. index++
  78. }
  79. sort.Strings(keys)
  80. builder := strings.Builder{}
  81. pos := 0
  82. paramsLen := len(keys)
  83. for _, key := range keys {
  84. value := parameters[key]
  85. builder.WriteString(utils.PercentEncode(key))
  86. builder.WriteString(consts.QuerySeparator)
  87. builder.WriteString(utils.PercentEncode(value))
  88. if pos != paramsLen-1 {
  89. builder.WriteString(consts.ParameterSeparator)
  90. pos++
  91. }
  92. }
  93. canonicalQueryString := builder.String()
  94. keyBytes, err := utils.Base64Decode(*credential.PrivateKey)
  95. if err != nil {
  96. return err
  97. }
  98. privateKey, err := x509.ParsePKCS8PrivateKey(keyBytes)
  99. if err != nil {
  100. return errs.NewCredentialError("ParsePKCS8PrivateKey decode error", err)
  101. }
  102. rsaPrivateKey, ok := privateKey.(*rsa.PrivateKey)
  103. if !ok {
  104. return errs.NewCredentialError("privateKey convert error", nil)
  105. }
  106. signature, err := utils.GenerateRSASignature(utils.StringToBytes(canonicalQueryString), rsaPrivateKey)
  107. if err != nil {
  108. return errs.NewCredentialError("GenerateRSASignature error", err)
  109. }
  110. signStr := utils.Base64Encode(signature)
  111. request.QueryParams["sign"] = signStr
  112. request.QueryParams["flowdId"] = flowdId
  113. GetCredentialManager(CredentialAkSk).Sign(request, credential)
  114. return nil
  115. }
  116. func (mop *MopCredential) Encrypt(data []byte, publicKey string) (string, error) {
  117. if utils.IsUnSet(publicKey) {
  118. return "", errs.NewInvalidParameterError("RSA public key can not be null", nil)
  119. }
  120. keyBytes, err := utils.Base64Decode(publicKey)
  121. if err != nil {
  122. return "", errs.NewInvalidParameterError("RSA public key is invalid", nil)
  123. }
  124. publicKeyInterface, err := x509.ParsePKIXPublicKey(keyBytes)
  125. if err != nil {
  126. return "", errs.NewCredentialError("ParsePKIXPublicKey decode error", nil)
  127. }
  128. rsaPublicKey, ok := publicKeyInterface.(*rsa.PublicKey)
  129. if !ok {
  130. return "", errs.NewCredentialError("publicKey convert error", nil)
  131. }
  132. var encryptedData []byte
  133. for len(data) > 0 {
  134. var chunk []byte
  135. if len(data) > 64 {
  136. chunk, err = rsa.EncryptPKCS1v15(rand.Reader, rsaPublicKey, data[:64])
  137. data = data[64:]
  138. } else {
  139. chunk, err = rsa.EncryptPKCS1v15(rand.Reader, rsaPublicKey, data)
  140. data = nil
  141. }
  142. if err != nil {
  143. return "", errs.NewCredentialError("RSAPublicKeyEncrypt error", err)
  144. }
  145. encryptedData = append(encryptedData, chunk...)
  146. }
  147. return utils.Base64Encode(encryptedData), nil
  148. }
  149. func (mop *MopCredential) Decrypt(originStr string, privateKey string) (string, error) {
  150. if utils.IsUnSet(privateKey) {
  151. return "", errs.NewInvalidParameterError("RSA private key can not be null", nil)
  152. }
  153. data, err := utils.Base64Decode(originStr)
  154. if err != nil {
  155. return "", err
  156. }
  157. keyBytes, err := utils.Base64Decode(privateKey)
  158. if err != nil {
  159. return "", errs.NewInvalidParameterError("RSA private key is invalid", nil)
  160. }
  161. privateKeyInterface, err := x509.ParsePKCS8PrivateKey(keyBytes)
  162. if err != nil {
  163. return "", errs.NewCredentialError("ParsePKCS8PrivateKey decode error", nil)
  164. }
  165. rsaPrivateKey, ok := privateKeyInterface.(*rsa.PrivateKey)
  166. if !ok {
  167. return "", errs.NewCredentialError("privateKey convert error", nil)
  168. }
  169. var decryptedData []byte
  170. for len(data) > 0 {
  171. var chunk []byte
  172. if len(data) > 75 {
  173. chunk, err = rsa.DecryptPKCS1v15(rand.Reader, rsaPrivateKey, data[:75])
  174. data = data[75:]
  175. } else {
  176. chunk, err = rsa.DecryptPKCS1v15(rand.Reader, rsaPrivateKey, data)
  177. data = nil
  178. }
  179. if err != nil {
  180. return "", errs.NewCredentialError("RSAPrivateKeyDecrypt error", err)
  181. }
  182. decryptedData = append(decryptedData, chunk...)
  183. }
  184. return string(decryptedData), nil
  185. }
  186. func (aksk *AKSKCredential) Sign(request *request.HttpRequest, credential *Credential) error {
  187. request.ConvertQueryParamsFromPath()
  188. params := make(map[string]string)
  189. for key, value := range request.QueryParams {
  190. params[key] = value
  191. }
  192. params[consts.AccessKey] = *credential.AccessKey
  193. loc, _ := time.LoadLocation("Asia/Shanghai")
  194. var now time.Time
  195. if loc != nil {
  196. now = time.Now().In(loc)
  197. } else {
  198. now = time.Now()
  199. }
  200. params[consts.Timetamp] = now.Format(consts.TimestampFormat)
  201. params[consts.SignatureMethod] = consts.SignatureMethodValue
  202. params[consts.SignatureVersion] = consts.SignatureVersionValue
  203. params[consts.SignatureNonce] = utils.Nonce()
  204. keys := make([]string, len(params))
  205. index := 0
  206. for key := range params {
  207. keys[index] = key
  208. index++
  209. }
  210. sort.Strings(keys)
  211. builder := strings.Builder{}
  212. pos := 0
  213. paramsLen := len(keys)
  214. for _, key := range keys {
  215. value := params[key]
  216. builder.WriteString(utils.PercentEncode(key))
  217. builder.WriteString(consts.QuerySeparator)
  218. builder.WriteString(utils.PercentEncode(value))
  219. if pos != paramsLen-1 {
  220. builder.WriteString(consts.ParameterSeparator)
  221. pos++
  222. }
  223. }
  224. canonicalQueryString := builder.String()
  225. hashString := utils.ConvertToHexString(utils.Sha256Encode(canonicalQueryString))
  226. unescapedPath, err := url.QueryUnescape(request.Path)
  227. if nil != err {
  228. return errs.NewSignatureError(err.Error(), err)
  229. }
  230. builder.Reset()
  231. builder.WriteString(strings.ToUpper(request.Method))
  232. builder.WriteString(consts.LineSeparator)
  233. builder.WriteString(utils.PercentEncode(unescapedPath))
  234. builder.WriteString(consts.LineSeparator)
  235. builder.WriteString(hashString)
  236. stringToSign := builder.String()
  237. signature := utils.ConvertToHexString(utils.HmacSha256(stringToSign, consts.SecretKeyPrefix+*credential.SecretKey))
  238. builder.Reset()
  239. builder.WriteString(unescapedPath)
  240. builder.WriteString(consts.QueryStartSymbol)
  241. builder.WriteString(canonicalQueryString)
  242. builder.WriteString(consts.ParameterSeparator)
  243. builder.WriteString(consts.Signature)
  244. builder.WriteString(consts.QuerySeparator)
  245. builder.WriteString(utils.PercentEncode(signature))
  246. request.Path = builder.String()
  247. return nil
  248. }
  249. func (aksk *AKSKCredential) Encrypt(data []byte, publicKey string) (string, error) {
  250. return string(data), nil
  251. }
  252. func (aksk *AKSKCredential) Decrypt(originStr string, privateKey string) (string, error) {
  253. return originStr, nil
  254. }
  255. func CredentialTypePointer(a CredentialType) *CredentialType {
  256. return &a
  257. }
  258. func EncryptionTypePointer(a EncryptionType) *EncryptionType {
  259. return &a
  260. }