package com.chenyang.nse.bussiness.kms.service.impl;

import com.chenyang.nse.bussiness.kms.model.Kms;
import com.chenyang.nse.bussiness.kms.model.KmsException;
import com.chenyang.nse.bussiness.kms.service.KmsService;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import java.nio.charset.StandardCharsets;
import java.security.Key;
import java.security.Security;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.binary.Hex;
import org.apache.http.HttpHost;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StreamUtils;

@Service
public class KmsServiceImpl implements KmsService {
   protected Logger logger = LoggerFactory.getLogger(this.getClass());
   @Autowired
   public HttpClient httpClient;
   private Gson gson = new Gson();

   public String obtainChallengeCode() {
      HttpPost httpPost = new HttpPost("/api/getChallengeCode");

      String var11;
      try {
         httpPost.addHeader("Content-Type", "application/json");
         JsonObject json = new JsonObject();
         json.addProperty("accessKey", Kms.Credential.getInstance().getAccesskey());
         String requestBody = json.toString();
         this.logger.info(requestBody);
         StringEntity entity = new StringEntity(requestBody);
         httpPost.setEntity(entity);
         HttpHost httpHost = new HttpHost(Kms.Credential.getInstance().getHost(), Kms.Credential.getInstance().getPort(), Kms.Credential.getInstance().getProtocol());
         HttpResponse res = this.httpClient.execute(httpHost, httpPost);
         int code = res.getStatusLine().getStatusCode();
         this.logger.info("code={}", code);
         String body = StreamUtils.copyToString(res.getEntity().getContent(), StandardCharsets.UTF_8);
         this.logger.info(body);
         JsonObject bodyJson = (JsonObject)this.gson.fromJson(body, JsonObject.class);
         if (!bodyJson.get("success").getAsBoolean()) {
            throw new KmsException(body);
         }

         String challengeCode = bodyJson.get("data").getAsJsonObject().get("challengeCode").getAsString();
         var11 = challengeCode;
      } catch (KmsException kmse) {
         throw kmse;
      } catch (Exception e) {
         this.logger.error(e.getMessage(), e);
         throw new KmsException(e.getMessage(), e);
      } finally {
         httpPost.releaseConnection();
      }

      return var11;
   }

   protected String buildTokenBody(String challengeCode) {
      byte[] challengeCodeBytes = Base64.decodeBase64(challengeCode);
      byte[] accessKeyBytes = Kms.Credential.getInstance().getAccesskey().getBytes(StandardCharsets.UTF_8);
      byte[] plainBytes = new byte[challengeCodeBytes.length + accessKeyBytes.length];
      System.arraycopy(challengeCodeBytes, 0, plainBytes, 0, challengeCodeBytes.length);
      System.arraycopy(accessKeyBytes, 0, plainBytes, challengeCodeBytes.length, accessKeyBytes.length);
      byte[] keyBytes = Kms.Credential.getInstance().getSecretkey().getBytes(StandardCharsets.UTF_8);
      byte[] cypherBytes = this.sm4EncryptPkcs7Padding(keyBytes, plainBytes);
      String cypherText = new String(Base64.encodeBase64(cypherBytes, false), StandardCharsets.UTF_8);
      JsonObject json = new JsonObject();
      json.addProperty("accessKey", Kms.Credential.getInstance().getAccesskey());
      json.addProperty("secret", cypherText);
      String body = this.gson.toJson(json);
      this.logger.info(body);
      return body;
   }

   public String obtainAccessToken(String challengeCode) {
      HttpPost httpPost = new HttpPost("/api/getChallengeToken");

      String var11;
      try {
         httpPost.addHeader("Content-Type", "application/json");
         String tokenBody = this.buildTokenBody(challengeCode);
         StringEntity entity = new StringEntity(tokenBody);
         httpPost.setEntity(entity);
         HttpHost httpHost = new HttpHost(Kms.Credential.getInstance().getHost(), Kms.Credential.getInstance().getPort(), Kms.Credential.getInstance().getProtocol());
         HttpResponse res = this.httpClient.execute(httpHost, httpPost);
         int code = res.getStatusLine().getStatusCode();
         this.logger.info("code={}", code);
         String body = StreamUtils.copyToString(res.getEntity().getContent(), StandardCharsets.UTF_8);
         this.logger.info(body);
         JsonObject bodyJson = (JsonObject)this.gson.fromJson(body, JsonObject.class);
         if (!bodyJson.get("success").getAsBoolean()) {
            throw new KmsException(body);
         }

         String accessToken = bodyJson.get("data").getAsJsonObject().get("accessToken").getAsString();
         var11 = accessToken;
      } catch (KmsException kmse) {
         throw kmse;
      } catch (Exception e) {
         this.logger.error(e.getMessage(), e);
         throw new KmsException(e.getMessage(), e);
      } finally {
         httpPost.releaseConnection();
      }

      return var11;
   }

   public String createDataKey(String masterKey, String accessToken) {
      HttpPost httpPost = new HttpPost("/api/generateDataKey");

      String var13;
      try {
         httpPost.addHeader("Content-Type", "application/json");
         JsonObject json = new JsonObject();
         json.addProperty("keyId", masterKey);
         json.addProperty("keySpec", "SM4");
         json.addProperty("numberOfBytes", 16);
         json.addProperty("accessToken", accessToken);
         String dataKeyBody = json.toString();
         this.logger.info(dataKeyBody);
         StringEntity entity = new StringEntity(dataKeyBody);
         httpPost.setEntity(entity);
         HttpHost httpHost = new HttpHost(Kms.Credential.getInstance().getHost(), Kms.Credential.getInstance().getPort(), Kms.Credential.getInstance().getProtocol());
         HttpResponse res = this.httpClient.execute(httpHost, httpPost);
         int code = res.getStatusLine().getStatusCode();
         this.logger.info("code={}", code);
         String body = StreamUtils.copyToString(res.getEntity().getContent(), StandardCharsets.UTF_8);
         this.logger.info(body);
         JsonObject bodyJson = (JsonObject)this.gson.fromJson(body, JsonObject.class);
         if (!bodyJson.get("success").getAsBoolean()) {
            throw new KmsException(body);
         }

         String ciphertextBlob = bodyJson.get("data").getAsJsonObject().get("ciphertextBlob").getAsString();
         var13 = ciphertextBlob;
      } catch (KmsException kmse) {
         throw kmse;
      } catch (Exception e) {
         this.logger.error(e.getMessage(), e);
         throw new KmsException(e.getMessage(), e);
      } finally {
         httpPost.releaseConnection();
      }

      return var13;
   }

   public byte[] sm4EncryptPkcs7Padding(byte[] keyBytes, byte[] plain) {
      try {
         Key key = new SecretKeySpec(keyBytes, "SM4");
         Cipher cipher = Cipher.getInstance("SM4/CBC/NoPadding", "BC");
         cipher.init(1, key, new IvParameterSpec(Kms.Credential.getInstance().getIvbytes()));
         return cipher.doFinal(plain);
      } catch (Exception e) {
         this.logger.error(e.getMessage(), e);
         throw new RuntimeException(e.getMessage(), e);
      }
   }

   public byte[] sm4DecryptPkcs7Padding(byte[] keyBytes, byte[] ciphertext) {
      try {
         Key key = new SecretKeySpec(keyBytes, "SM4");
         Cipher out = Cipher.getInstance("SM4/CBC/NoPadding", "BC");
         out.init(2, key, new IvParameterSpec(Kms.Credential.getInstance().getIvbytes()));
         return out.doFinal(ciphertext);
      } catch (Exception e) {
         this.logger.error(e.getMessage(), e);
         throw new RuntimeException(e.getMessage(), e);
      }
   }

   public String obtainSecretKey(String masterKey, String accessToken, String dataKey) {
      HttpPost httpPost = new HttpPost("/api/decrypt");

      String var18;
      try {
         httpPost.addHeader("Content-Type", "application/json");
         JsonObject json = new JsonObject();
         json.addProperty("keyId", masterKey);
         json.addProperty("ciphertextBlob", dataKey);
         json.addProperty("accessToken", accessToken);
         String dataKeyBody = json.toString();
         this.logger.info(dataKeyBody);
         StringEntity entity = new StringEntity(dataKeyBody);
         httpPost.setEntity(entity);
         HttpHost httpHost = new HttpHost(Kms.Credential.getInstance().getHost(), Kms.Credential.getInstance().getPort(), Kms.Credential.getInstance().getProtocol());
         HttpResponse res = this.httpClient.execute(httpHost, httpPost);
         int code = res.getStatusLine().getStatusCode();
         this.logger.info("code={}", code);
         String body = StreamUtils.copyToString(res.getEntity().getContent(), StandardCharsets.UTF_8);
         this.logger.info(body);
         JsonObject bodyJson = (JsonObject)this.gson.fromJson(body, JsonObject.class);
         if (!bodyJson.get("success").getAsBoolean()) {
            throw new KmsException(body);
         }

         String dataKeyPlainText = bodyJson.get("data").getAsJsonObject().get("plaintext").getAsString();
         byte[] keyBytes = Kms.Credential.getInstance().getSecretkey().getBytes(StandardCharsets.UTF_8);
         byte[] dataKeyPlainBytes = Base64.decodeBase64(dataKeyPlainText);
         byte[] secretKeyBytes = this.sm4DecryptPkcs7Padding(keyBytes, dataKeyPlainBytes);
         String secretKey = new String(Hex.encodeHex(secretKeyBytes, false));
         var18 = secretKey;
      } catch (KmsException kmse) {
         throw kmse;
      } catch (Exception e) {
         this.logger.error(e.getMessage(), e);
         throw new KmsException(e.getMessage(), e);
      } finally {
         httpPost.releaseConnection();
      }

      return var18;
   }

   static {
      Security.addProvider(new BouncyCastleProvider());
   }
}
