/* * Copyright 2024. Huawei Technologies Co., Ltd. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ package harmonyos import ( "crypto/ecdsa" "crypto/sha256" "crypto/x509" "encoding/hex" "encoding/json" "encoding/pem" "errors" "github.com/cristalhq/jwt/v3" "io/ioutil" "time" ) type JWTGenerator struct { } type IAPJWTClaims struct { // Iss Key issuer ID. Iss string `json:"iss"` // Aud Expected receiver of the JWT. The value is fixed at iap-v1. Aud string `json:"aud"` // Iat Time when the JWT is issued. The value is a UTC timestamp, in seconds. Iat int64 `json:"iat"` // Exp Time when the JWT expires. The value is a UTC timestamp, in seconds. exp-iat indicates the validity period of the JWT, which cannot exceed one hour. Exp int64 `json:"exp"` // Aid App ID. Aid string `json:"aid"` // Digest Hash value of the request body (JSON character string), which is used to verify the integrity of the body. The algorithm is SHA-256. Digest string `json:"digest"` } const ( // JWT_PRI_KEY_PATH Private key file path. JWT_PRI_KEY_PATH = "manifest/config/IAPKey.p8" // TODO: Need to replace it with the actual value. // ACTIVE_TIME JWT validity period, which is a UTC timestamp in seconds. The validity period cannot exceed 1 hour. ACTIVE_TIME_SECOND = 3600 // TODO: Need to replace it with the actual value. KID = "f35b90cf-48be-4bb9-bb66-f7e814d5521c" // TODO: Need to replace it with the actual value. ISSUER_ID = "002124f1-f9a9-468e-92ea-26561ea9c605" // TODO: Need to replace it with the actual business logic. APP_ID = "6917589392953468039" // TODO: Need to replace it with the actual business logic. ) func (jwtGenerator *JWTGenerator) GenJWT(bodyMap map[string]interface{}) (string, error) { privateKeyPEM, err := ioutil.ReadFile(JWT_PRI_KEY_PATH) if err != nil { // TODO: Need to replace it with the actual business logic. return "", err } block, _ := pem.Decode(privateKeyPEM) if block == nil { // TODO: Need to replace it with the actual business logic. return "", errors.New("the key content is empty") } privateKey, err := x509.ParsePKCS8PrivateKey(block.Bytes) if err != nil { // TODO: Need to replace it with the actual business logic. return "", err } ecdsaPrivateKey, ok := privateKey.(*ecdsa.PrivateKey) if !ok { // TODO: Need to replace it with the actual business logic. return "", errors.New("failed to convert private key to *ecdsa.PrivateKey") } signer, err := jwt.NewSignerES(jwt.ES256, ecdsaPrivateKey) if err != nil { // TODO: Need to replace it with the actual business logic. return "", err } payloadJson, err := json.Marshal(bodyMap) if err != nil { // TODO: Need to replace it with the actual business logic. return "", err } hash := sha256.New() hash.Write(payloadJson) sha256Sum := hash.Sum(nil) sha256Hex := hex.EncodeToString(sha256Sum) builder := jwt.NewBuilder(signer, jwt.WithKeyID(KID)) // TODO: Need to replace it with the actual business logic. signTime := time.Now().UTC().Unix() claims := IAPJWTClaims{ Iss: ISSUER_ID, // TODO: Need to replace it with the actual business logic. Aud: "iap-v1", Iat: signTime, Exp: signTime + ACTIVE_TIME_SECOND, Aid: APP_ID, // TODO: Need to replace it with the actual business logic. Digest: sha256Hex, } iapJwt, err := builder.Build(claims) if err != nil { // TODO: Need replace it with your business logic. return "", err } return iapJwt.String(), nil }