Key Management Service 예제
    • PDF

    Key Management Service 예제

    • PDF

    기사 요약

    Classic/VPC 환경에서 이용 가능합니다 .

    Key Management Service를 이용하여 봉투 암호화(Envelope Encryption)를 구현하는 예제를 소개합니다.

    주의

    Key Management Service 예제에서 소개하는 코드는 Key Management Service에 대한 이해를 돕기 위해 작성한 가상의 시나리오입니다. 예외 처리 등의 작업이 미비하며 실제 시나리오에 완벽하게 대응될 수 없으므로 실제 상황에 그대로 적용하지 않도록 주의해 주십시오.

    기밀 정보의 봉투 암호화

    기밀 정보의 봉투 암호화에 대한 시나리오와 예제를 설명합니다.

    시나리오

    네이버 클라우드 플랫폼을 사용 중인 웹 서비스 회사의 서버 개발자 A는 웹 서버에서 DB 서버에 접속하기 위한 DB 인증 정보를 암호화해야 한다는 다음과 같은 요구사항을 접수했습니다.

    • DB 인증 정보는 암호화되어 보호되어야 함
    • 모든 암호화 키는 표준 권고 수준으로 적절하게 생성, 운영, 보호되어야 함

    이를 위해 DB 인증 정보를 데이터 암호화 키 (DEK)로 암호화하고, DEK 역시 다른 키로 암호화하여 보관하기로 했습니다. 데이터 키를 암호화하는 상위 키인 마스터 키 (KEK)를 이용하기 위해 Key Management Service의 키 접근 권한을 신청했습니다. DEK를 암호화하고 복호화해야 하기 때문에 Key Management Service 키에 대한 Change/encrypt, Change/decrypt 그리고 View/getKeyInfo, View/getKeyList 권한을 부여 받은 후, 콘솔을 통해 키 Tag를 확인했습니다.
    A는 이미 Sub Account를 통해 알고 있었던 Access key와 Secret key를 네이버 클라우드 플랫폼 콘솔의 Sub Account에 접속하여 다시 확인했습니다. 그 후 이를 각각 NCP_ACCESS_KEY, NCP_SECRET_KEY라는 이름으로 환경 변수에 설정했습니다.
    또한 Key Management Service API를 직접 호출하기 위해서 API Gateway의 API Keys에서 Key Management Service 전용 API key를 확인했으나 없는 것을 확인하고, 계정 관리자에게 Key Management Service 전용 API key 생성을 요청했습니다. 계정 관리자로부터 Key Management Service API는 범용 API key를 사용해도 무방하다는 확인을 받은 후 범용 API key를 자신의 개발 환경 시스템에 NCP_API_KEY라는 이름의 환경 변수로 설정했습니다.
    DEK 역시 암호화 키 생성 권고 기준을 따르고 싶었던 A는 Key Management Service의 createCustomKey API를 통해 복잡한 키 생성 과정을 직접 수행할 필요 없이 high-entropy 키를 생성할 수 있음을 파악했습니다.
    DB 인증 정보의 암호화는 AES-CBC를 이용할 것이기 때문에 암/복호화에 이용되는 추가 정보인 IV(Initial Vector)값도 함께 관리되어야 합니다. 그래서 A는 DB 인증 정보와 데이터 키, 추가 암호화 정보를 다음과 같은 봉투 형태의 데이터로 관리하기로 했습니다.

    {
      "ciphertext": "암호화된 DB 인증 정보",
      "wrappedKey": "암호화된 데이터 암호화 키",
      "iv": "암호화에 사용할 추가 정보 <예시> IV 값"
    }
    

    예제 코드

    크리덴셜의 봉투 암호화 시나리오에 따라 Java로 작성한 봉투 암호화 생성 예제는 다음과 같습니다.

    public class EncryptCredential {
    
      // URI
      private static String KMS_API_BASE_URI = "https://kms.apigw.gov-ntruss.com";
    
      // END POINT
      private static String KMS_API_DECRYPT = "/keys/v1/%s/decrypt"; // Change/decrypt 권한 필요 (KMS API stage v1 사용)
      //private static String KMS_API_DECRYPT = "/keys/v2/%s/decrypt"; // Change/decrypt 권한 필요 (KMS API stage v2 사용)
      private static String KMS_API_CUSTOM_KEY = "/keys/v1/%s/createCustomKey"; // Change/encrypt 권한 필요 (KMS API stage v1 사용)
      //private static String KMS_API_CUSTOM_KEY = "/keys/v2/%s/createCustomKey"; // Change/encrypt 권한 필요 (KMS API stage v2 사용)
    
      // 샘플용 KEY TAG
      private static String KEY_TAG = "4165867476e68eca06e84c993708c23d22ca2cb6a51ac15750bd7e991ccadc39";
    
      private static String ncpAccessKey;
      private static String ncpSecretKey;
      private static String ncpApiKey;
    
      public static void main(String[] args) throws Exception {
        // API 자격 증명 정보를 시스템 환경 변수에 등록하여 사용
        ncpAccessKey = System.getenv("NCP_ACCESS_KEY");
        ncpSecretKey = System.getenv("NCP_SECRET_KEY");
        ncpApiKey = System.getenv("NCP_API_KEY");
    
        envelopCredential();
      }
    
      public static void envelopCredential() throws Exception {
        // 새로운 high-entropy 데이터 키 생성을 요청
        String wrappedDataKey = getCustomKey();
        // 최종적으로 보호하고자 하는 기밀 데이터
        String example_credential_json = "{\"AUTH\":\"THIS_IS_A_DB_CREDENTIAL\"}}";
    
        // 사용자가 보관할 암호화된 데이터 봉투(Envelop encryption 참고)
        String envelope = encrypt(example_credential_json, wrappedDataKey);
        // 이 예제 코드에서는 암호화된 데이터 봉투를 파일에 저장
        File envelopeFile = new File("credentialEnvelope.json");
        OutputStream os = new BufferedOutputStream(new FileOutputStream(envelopeFile));
    
        try {
          os.write(envelope.getBytes());
        } finally {
          os.close();
        }
      }
    
      private static String encrypt(Object obj, String wrappedDataKey) throws Exception {
        Map<String, String> envelope = new HashMap<>();
    
        // 데이터 키 unwrapping
        String dataKey = unwrapKey(wrappedDataKey);
    
        // 생성된 high-enrtopy 256 bit의 데이터 키를 AES-CBC 방식으로 암호화
        SecretKey secretKey = new SecretKeySpec(decodeFromBase64(dataKey),"AES");
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        cipher.init(Cipher.ENCRYPT_MODE, secretKey);
        byte[] iv = cipher.getParameters().getParameterSpec(IvParameterSpec.class).getIV();
        byte[] ciphertext = cipher.doFinal(obj.toString().getBytes());
    
        envelope.put("wrappedKey", wrappedDataKey);
        envelope.put("ciphertext", encodeToBase64(ciphertext));
        envelope.put("iv", encodeToBase64(iv));
    
        return JSONValue.toJSONString(envelope);
      }
    
      private static String unwrapKey(String sealedKey) throws Exception {
        String endPoint = String.format(KMS_API_DECRYPT, KEY_TAG);
    
        JSONObject data = new JSONObject();
        data.put("ciphertext", sealedKey);
        JSONObject respJsonObject = apiCaller(endPoint, data.toJSONString());
        String plaintext = (respJsonObject.get("plaintext")).toString();
        return plaintext;
      }
    
      private static String getCustomKey() throws Exception {
        String endPoint = String.format(KMS_API_CUSTOM_KEY, KEY_TAG);
    
        JSONObject data = new JSONObject();
        data.put("requestPlainKey", false);
        JSONObject respJsonObject = apiCaller(endPoint, data.toJSONString());
        return respJsonObject.get("ciphertext").toString();
      }
    
      private static JSONObject apiCaller(String endPoint, String data) throws Exception {
        HttpClient client = HttpClients.createDefault();
    
        long timestamp = System.currentTimeMillis();
        String signature = makeSignature(endPoint, timestamp);
        URIBuilder uriBuilder = new URIBuilder(KMS_API_BASE_URI);
        uriBuilder.setPath(endPoint);
    
        HttpPost request = new HttpPost(uriBuilder.build().toString());
        request.addHeader("x-ncp-apigw-timestamp", timestamp + "");
        request.addHeader("x-ncp-apigw-api-key", ncpApiKey); // v1을 사용하는 경우 필요
        //request.addHeader("x-ncp-apigw-api-key", ncpApiKey); // v2를 사용하는 경우 불필요
        request.addHeader("x-ncp-iam-access-key", ncpAccessKey);
        request.addHeader("x-ncp-apigw-signature-v1", signature);
        request.addHeader("Content-Type", "application/json");
        request.setEntity(new StringEntity(data));
    
        HttpResponse response = client.execute(request);
        String responseBody = EntityUtils.toString(response.getEntity());
        JSONParser parser = new JSONParser();
        JSONObject repsObj = (JSONObject) parser.parse(responseBody);
        JSONObject dataObj = (JSONObject) repsObj.get("data");
        return dataObj;
      }
    
      private static String encodeToBase64(byte[] bytesToEncode) {
        return Base64.getEncoder().encodeToString(bytesToEncode);
      }
    
      private static byte[] decodeFromBase64(String stringToDecode) {
        return Base64.getDecoder().decode(stringToDecode);
      }
    
      // API Gateway  인증용 API 호출 시그니처 생성 (API Gateway 사용 가이드 참고)
      private static String makeSignature(String uri , long timestamp) throws Exception {
        String message = new StringBuilder()
          .append("POST").append(" ").append(uri).append("\n")
          .append(timestamp).append("\n")
          .append(ncpApiKey).append("\n") // v1을 사용하는 경우 필요
          //.append(ncpApiKey).append("\n") // v2를 사용하는 경우 불필요
          .append(ncpAccessKey)
          .toString();
    
        SecretKeySpec signingKey = new SecretKeySpec(ncpSecretKey.getBytes("UTF-8"), "HmacSHA256");
        Mac mac = Mac.getInstance("HmacSHA256");
        mac.init(signingKey);
        byte[] rawHmac = mac.doFinal(message.getBytes("UTF-8"));
        String encodeBase64String = Base64.getEncoder().encodeToString(rawHmac);
        return encodeBase64String;
      }
    
    }
    
    

    생성 결과

    예제 코드의 생성 결과는 다음과 같습니다.

    {
      "ciphertext":"wh6wryZ5MUrzlzd7EW9OYNek+3taxNVnxAcUPBRR6vtDH29tDrFxLyNukqUT3s7i",
      "iv":"HDlrArTVqwHQJRx9IhtqzQ==",
      "wrappedKey":"ncpkms:v1:e0AGESFjKj7xFtCxW1zfGFyZ3G\/4mc51mAMMu1n2hHNLsI4X9h5NKRKx0avz+1ky7\/+7aCd5SAjCOlnV"
    }
    

    암호화된 봉투(Envelope)의 사용

    암호화된 봉투 (Envelope)의 사용을 돕기 위한 가상 시나리오와 예제 코드를 소개합니다.

    시나리오

    기밀정보의 봉투 암호화 시나리오를 통해 암호화 처리한 DB 인증 정보가 담긴 봉투를 실제 서버 코드에서 이용해야 합니다. 이를 테스트하기 위해 개발자 A는 DB 접속 전 봉투의 암호문을 복호화하여 DB 인증 정보로 변환하는 코드를 작성합니다.

    예제 코드

    암호화된 봉투 (Envelope)의 사용 시나리오에 따라 Java로 작성한 예제는 다음과 같습니다.

    public class ClientApiSample {
    
      // URI
      private static String KMS_API_BASE_URI = "https://kms.apigw.gov-ntruss.com";
    
      // END POINT
      private static String KMS_API_DECRYPT = "/keys/v1/%s/decrypt"; // Change/decrypt 권한 필요 (KMS API stage v1 사용)
      //private static String KMS_API_DECRYPT = "/keys/v2/%s/decrypt"; // Change/decrypt 권한 필요 (KMS API stage v2 사용)
    
      // KEY TAG
      private static String KEY_TAG = "1bc86ca1be3b062cf8503d0a7e6d3717fe3a1c0480e309b724b26bf961e1f3c6";
    
      private static String ncpAccessKey;
      private static String ncpSecretKey;
      private static String ncpApiKey;
    
      public static void main(String[] args) throws Exception {
        // API 자격 증명 정보를 시스템 환경 변수에 등록하여 사용
        ncpAccessKey = System.getenv("NCP_ACCESS_KEY");
        ncpSecretKey = System.getenv("NCP_SECRET_KEY");
        ncpApiKey = System.getenv("NCP_API_KEY");
    
        String dbCredential = getCredential();
      }
    
      public static String getCredential() throws Exception {
        // 사용자가 보관할 암호화된 데이터 봉투(Envelop encryption 참고)
        File envelopeFile = new File("credentialEnvelope.json");
        InputStream is = new BufferedInputStream(new FileInputStream(envelopeFile));
    
        String envelope = new String(Files.readAllBytes(Paths.get("credentialEnvelope.json")));
        JSONParser parser = new JSONParser();
        JSONObject envelopeJson = (JSONObject) parser.parse(envelope);
        String wrappedDataKey = envelopeJson.get("wrappedKey").toString();
        String ciphertext = envelopeJson.get("ciphertext").toString();
        String iv = envelopeJson.get("iv").toString();
    
        return decrypt(ciphertext, wrappedDataKey, iv);
      }
    
      private static String decrypt(String ciphertext, String wrappedDataKey, String iv) throws Exception {
    
        String dataKey = unwrapKey(wrappedDataKey);
        IvParameterSpec ivParameterSpec = new IvParameterSpec(decodeFromBase64(iv));
        SecretKey secretKey = new SecretKeySpec(decodeFromBase64(dataKey), "AES");
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        cipher.init(Cipher.DECRYPT_MODE, secretKey, ivParameterSpec);
        byte[] plaintext = cipher.doFinal(decodeFromBase64(ciphertext));
    
        return new String(plaintext);
      }
    
      private static String unwrapKey(String sealedKey) throws Exception {
        String endPoint = String.format(KMS_API_DECRYPT, KEY_TAG);
    
        JSONObject data = new JSONObject();
        data.put("ciphertext", sealedKey);
        JSONObject respJsonObject = apiCaller(endPoint, data.toJSONString());
        String plaintext = (respJsonObject.get("plaintext")).toString();
        return plaintext;
      }
    
      private static JSONObject apiCaller(String endPoint, String data) throws Exception {
        HttpClient client = HttpClients.createDefault();
    
        long timestamp = System.currentTimeMillis();
        String signature = makeSignature(endPoint, timestamp);
        URIBuilder uriBuilder = new URIBuilder(KMS_API_BASE_URI);
        uriBuilder.setPath(endPoint);
    
        HttpPost request = new HttpPost(uriBuilder.build().toString());
        request.addHeader("x-ncp-apigw-timestamp", timestamp + "");
        request.addHeader("x-ncp-apigw-api-key", ncpApiKey); // v1을 사용하는 경우 필요
        //request.addHeader("x-ncp-apigw-api-key", ncpApiKey); // v2를 사용하는 경우 불필요
        request.addHeader("x-ncp-iam-access-key", ncpAccessKey);
        request.addHeader("x-ncp-apigw-signature-v1", signature);
        request.addHeader("Content-Type", "application/json");
        request.setEntity(new StringEntity(data));
    
        HttpResponse response = client.execute(request);
        String responseBody = EntityUtils.toString(response.getEntity());
        JSONParser parser = new JSONParser();
        JSONObject repsObj = (JSONObject) parser.parse(responseBody);
        JSONObject dataObj = (JSONObject) repsObj.get("data");
        return dataObj;
      }
    
      private static byte[] decodeFromBase64(String stringToDecode) {
        return Base64.getDecoder().decode(stringToDecode);
      }
    
      // API Gateway 인증용 API 호출 시그니처 생성 (API Gateway 사용 가이드 참조)
      private static String makeSignature(String uri , long timestamp) throws Exception {
        String message = new StringBuilder()
          .append("POST").append(" ").append(uri).append("\n")
          .append(timestamp).append("\n")
          .append(ncpApiKey).append("\n") // v1을 사용하는 경우 필요
          //.append(ncpApiKey).append("\n") // v2를 사용하는 경우 불필요
          .append(ncpAccessKey)
          .toString();
    
        SecretKeySpec signingKey = new SecretKeySpec(ncpSecretKey.getBytes("UTF-8"), "HmacSHA256");
        Mac mac = Mac.getInstance("HmacSHA256");
        mac.init(signingKey);
        byte[] rawHmac = mac.doFinal(message.getBytes("UTF-8"));
        String encodeBase64String = Base64.getEncoder().encodeToString(rawHmac);
        return encodeBase64String;
      }
    
    }
    

    데이터 암호화 키 관리

    데이터 암호화 키 (DEK) 관리의 이해를 돕기 위한 가상 시나리오와 예제 코드를 소개합니다.

    시나리오

    기밀정보와 DEK를 암호화하여 함께 묶어 보관하는 방식은 데이터 보호에 있어 가장 안전하다고 알려진 방식입니다. 하지만 이것이 전부가 아닙니다. 모든 암호화 키는 알려진 암호학적 취약점들에 대비하기 위해 주기적인 회전(갱신)이 필요합니다.
    앞서 소개했던 예제 코드에서 KEY_TAG로 이용하던 마스터 키는 필수적으로 일정 주기마다(최대 365일) 자동으로 회전되도록 설정되어 있습니다. 뿐만 아니라 Key Management Service 관리자(또는 키 관리자)에 의해 수동으로 회전될 수도 있습니다.
    개발자 A가 DB 인증 정보의 암호화에 직접 이용하던 DEK는 마스터 키로 암호화되어 있기 때문에 마스터 키가 회전되면 암호화된 DEK를 회전된 새 마스터 키로 재암호화해야 합니다. 재암호화는 Key Management Service의 reencrypt API를 통해 간편하게 수행할 수 있습니다. reencrypt API는 가장 최신 버전의 키로 기존 암호문을 재암호화합니다.
    A는 키 사용 권한이 할당될 때 메일을 통해 알림을 받은 것처럼 키가 회전되면 이에 대한 알림도 받을 것입니다. 알림을 받으면 가능한 빠른 시일내에 재암호화를 수행해야 합니다. 이를 위해 A는 키 회전 알림을 받으면 수행할 코드를 다음과 같이 작성했습니다. 이제 DEK는 회전된 새 버전으로 재암호화되어 새로운 봉투를 생성합니다. 재암호화 이후에는 기존 봉투를 삭제하는 것이 안전합니다. 하지만, 데이터 유실을 방지하기 위해 재암호화 된 봉투를 직접 확인하고 삭제하는 것이 좋습니다. 따라서, 기존의 봉투를 즉시 덮어쓰지 않고 새로운 봉투를 생성하고 확인 후에 삭제하는 방식으로 진행하고자 합니다.

    예제 코드

    DEK 관리 시나리오에 따라 Java로 작성한 예제는 다음과 같습니다.

    public class ClientApiSample {
    
      // URI
      private static String KMS_API_BASE_URI = "https://kms.apigw.gov-ntruss.com";
    
      // END POINT
      private static String KMS_API_REENCRYPT = "/keys/v1/%s/reencrypt"; // KMS API stage v1 사용
      // private static String KMS_API_REENCRYPT = "/keys/v2/%s/reencrypt"; // KMS API stage v2 사용
    
      // KEY TAG
      private static String KEY_TAG = "1bc86ca1be3b062cf8503d0a7e6d3717fe3a1c0480e309b724b26bf961e1f3c6";
    
      private static String ncpAccessKey;
      private static String ncpSecretKey;
      private static String ncpApiKey;
    
      public static void main(String[] args) throws Exception {
        ncpAccessKey = System.getenv("NCP_ACCESS_KEY");
        ncpSecretKey = System.getenv("NCP_SECRET_KEY");
        ncpApiKey = System.getenv("NCP_API_KEY");
    
        reenvelopCredential();
      }
    
      private static void reenvelopCredential() throws Exception {
        String envelope = new String(Files.readAllBytes(Paths.get("credentialEnvelope.json")));
        JSONParser parser = new JSONParser();
        JSONObject envelopeJson = (JSONObject) parser.parse(envelope);
        String wrappedDataKey = envelopeJson.get("wrappedKey").toString();
        String ciphertext = envelopeJson.get("ciphertext").toString();
        String iv = envelopeJson.get("iv").toString();
    
        // 암호화된 데이터키를 최신 버전으로 재암호화
        String rewrappedDataKey = rewrapKey(wrappedDataKey);
    
        Map<String, String> newEnvelope = new HashMap<>();
        // 암호문과 iv는 변경 없으며 재암호화된 키만 변경
        newEnvelope.put("wrappedKey", rewrappedDataKey);
        newEnvelope.put("ciphertext", ciphertext);
        newEnvelope.put("iv", iv);
    
        String newEnvelopeJson = JSONValue.toJSONString(newEnvelope);
    
        // 새로운 봉투 생성(확인 후 기존 봉투 제거 필요)
        File newEnvelopeFile = new File("credentialEnvelope_new.json");
        OutputStream os = new BufferedOutputStream(new FileOutputStream(newEnvelopeFile));
    
        try {
          os.write(newEnvelopeJson.getBytes());
        } finally {
          os.close();
        }
      }
    
      private static String rewrapKey(String wrappedDataKey) throws Exception {
        String endPoint = String.format(KMS_API_REENCRYPT, KEY_TAG);
    
        JSONObject data = new JSONObject();
        data.put("ciphertext", wrappedDataKey);
    
        JSONObject respJsonObject = apiCaller(endPoint, data.toJSONString());
        String ciphertext = respJsonObject.get("newCiphertext").toString();
        return ciphertext;
      }
    
      private static JSONObject apiCaller(String endPoint, String data) throws Exception {
        HttpClient client = HttpClients.createDefault();
    
        long timestamp = System.currentTimeMillis();
        String signature = makeSignature(endPoint, timestamp);
        URIBuilder uriBuilder = new URIBuilder(KMS_API_BASE_URI);
        uriBuilder.setPath(endPoint);
    
        HttpPost request = new HttpPost(uriBuilder.build().toString());
        request.addHeader("x-ncp-apigw-timestamp", timestamp + "");
        request.addHeader("x-ncp-apigw-api-key", ncpApiKey); // v1을 사용하는 경우 필요
        //request.addHeader("x-ncp-apigw-api-key", ncpApiKey); // v2를 사용하는 경우 불필요
        request.addHeader("x-ncp-iam-access-key", ncpAccessKey);
        request.addHeader("x-ncp-apigw-signature-v1", signature);
        request.addHeader("Content-Type", "application/json");
        request.setEntity(new StringEntity(data));
    
        HttpResponse response = client.execute(request);
        String responseBody = EntityUtils.toString(response.getEntity());
        JSONParser parser = new JSONParser();
        JSONObject repsObj = (JSONObject) parser.parse(responseBody);
        JSONObject dataObj = (JSONObject) repsObj.get("data");
        return dataObj;
      }
    
      private static String makeSignature(String uri , long timestamp) throws Exception {
        String message = new StringBuilder()
          .append("POST").append(" ").append(uri).append("\n")
          .append(timestamp).append("\n")
          .append(ncpApiKey).append("\n") // v1을 사용하는 경우 필요
          //.append(ncpApiKey).append("\n") // v2 사용하는 경우 불필요
          .append(ncpAccessKey)
          .toString();
    
        SecretKeySpec signingKey = new SecretKeySpec(ncpSecretKey.getBytes("UTF-8"), "HmacSHA256");
        Mac mac = Mac.getInstance("HmacSHA256");
        mac.init(signingKey);
        byte[] rawHmac = mac.doFinal(message.getBytes("UTF-8"));
        String encodeBase64String = Base64.getEncoder().encodeToString(rawHmac);
        return encodeBase64String;
      }
    }
    

    생성 결과

    예제 코드의 생성 결과는 다음과 같습니다.

    {
      "ciphertext":"wh6wryZ5MUrzlzd7EW9OYNek+3taxNVnxAcUPBRR6vtDH29tDrFxLyNukqUT3s7i",
      "iv":"HDlrArTVqwHQJRx9IhtqzQ==",
      "wrappedKey":"ncpkms:v2:lNZubJHJ4coJConKPBf4gYghFN0h\/rjHmOBtvVbTXmXynRcKhPxPNrjkCTgurBZ4a7Fb7+\/8dVKcC33R"
    }
    

    Java SDK 사용

    Key Management Service API에서 제공하는 Java SDK(Maven project)를 이용하여 간편하게 API Gateway를 통해 Key Management Service API를 호출하는 예제를 소개합니다.

    참고

    Key Management Service Java Client SDK 다운로드는 Key Management Service 사용 준비를 참조해 주십시오.

    연결

    모든 요청은 ApiClient 객체를 통해 호출됩니다. ApiClient 객체는 인증 정보를 설정하여 생성합니다. 방법은 다음과 같습니다.
    인증 정보 설정: Key Management Service API는 API Gateway를 통해 호출되며, API Gateway에 등록된 API Key 인증과 Sub Account(IAM) 인증을 수행합니다.

    • 프로퍼티 파일을 이용한 인증
      • 인증 정보를 설정한 프로퍼티 파일을 이용해 PropertiesFileCredentialsProvider 객체를 생성하여 인증을 수행합니다.
        type=iam
        apiKey="API Gateway에 설정된 API Key"
        accessKey="Sub Account에 설정된 서브계정의 Access Key"
        secretKey="Sub Account에 설정된 서브계정의 Secret Key"
        
        위 형태로 credentials.properties라는 이름의 인증 정보 파일을 생성합니다. credentials.properties는 적절한 보호와 접근 제어를 통해 유출되지 않도록 주의해 주십시오. credentials.properties이 준비되면 미리 정의된 형태의 빌더로 ApiClient 객체를 생성합니다.
      • Java로 작성한 예제 코드는 다음과 같습니다.
        public void setUp() {
          apiClient = new ApiClient.ApiClientBuilder()
            .addMarshaller(JsonMarshaller.getInstance())
            .addMarshaller(XmlMarshaller.getInstance())
            .addMarshaller(FormMarshaller.getInstance())
            .setCredentials(new PropertiesFileCredentialsProvider("credentials.properties").getCredentials()) // 인증 정보 설정
            .setLogging(true)
            .build();
        
          api = new V1Api(apiClient);
        }
        
    • Server Role을 통한 인증
      • 네이버 클라우드 플랫폼 VPC 환경의 Server에서 사용할 수 있는 인증 방식입니다. VPC Server에서 KMS API를 사용하는 경우에는 Server Role을 통해 별도의 인증정보 입력 없이 Java SDK를 사용할 수 있습니다. 정책 및 역할 설정에 대한 내용은 Sub Account 정책 및 역할 관리를 참조해 주십시오. 정책은 NCP_KMS_MANAGER를, Role 소유 리소스는 KMS Java SDK 사용하는 VPC Server를 지정합니다.
        참고

        현재 사용자 정의 정책 사용을 위해 개선이 진행 중이므로 사용자 정의 정책 설정이 적용되기 전까지 NCP_KMS_MANAGER를 설정하여 사용해 주십시오.

      • 설정이 완료되면, ServerRoleCredentialsProvider 객체를 이용하여 미리 정의된 형태의 빌더로 ApiClient 객체를 생성합니다.
      • Java로 작성한 예제 코드는 다음과 같습니다.
        public void setUp() {
          apiClient = new ApiClient.ApiClientBuilder()
            .addMarshaller(JsonMarshaller.getInstance())
            .addMarshaller(XmlMarshaller.getInstance())
            .addMarshaller(FormMarshaller.getInstance())
            .setCredentialsProvider(new ServerRoleCredentialsProvider()) // Server Role 인증
            .setLogging(true)
            .build();
        
          api = new V1Api(apiClient);
        }
        

    API 호출

    Key Management Service에서 생성한 키를 사용하여 암/복호화 및 서명/검증을 하기 위한 API를 호출하는 방법과 호출 예제를 소개합니다.

    • 암호화

      • 호출 방법은 다음과 같습니다.
        Encrypt 참조
      • 호출 예제는 다음과 같습니다.
        public void keyTagEncryptPostTest() throws ApiException, SdkException {
            String keyTag = "53fdfdc1d875625d9cffc317e9c729c1febc5849328eb15b7b75ba17eb17e70c";
            EncryptRequestBody body = new EncryptRequestBody();
            String plaintext = Base64.getEncoder().encodeToString("This is a test.".getBytes());
            body.setPlaintext(plaintext);
        
            try {
                api.keyTagEncryptPost(keyTag, body);
                // Handler Successful response
            } catch (ApiException e) {
                // Handler Failed response
                e.printStackTrace();
            } catch (SdkException e) {
                // Handle exceptions that occurred before communication with the server
                e.printStackTrace();
            }
        }
        
    • 복호화

      • 호출 방법은 다음과 같습니다.
        Decrypt 참조
      • 호출 예제는 다음과 같습니다.
        public void keyTagDecryptPostTest() throws ApiException, SdkException {
            String keyTag = "53fdfdc1d875625d9cffc317e9c729c1febc5849328eb15b7b75ba17eb17e70c";
            DecryptRequestBody body = new DecryptRequestBody();
            String ciphertext = "ncpkms:v1:eEEYwgBf/HGmqUEbTV/rASoJjneBjII+dOTnFYVOlvTnyw/+SFjwvjHpUg==";
            body.setCiphertext(ciphertext);
        
            try {
                api.keyTagDecryptPost(keyTag, body);
                // Handler Successful response
            } catch (ApiException e) {
                // Handler Failed response
                e.printStackTrace();
            } catch (SdkException e) {
                // Handle exceptions that occurred before communication with the server
                e.printStackTrace();
            }
        }
        
    • user custom key 생성

      • 호출 방법은 다음과 같습니다.
        Create user custom key 참조
      • 호출 예제는 다음과 같습니다.
        public void keyTagCreateCustomKeyPostTest() throws ApiException, SdkException {
            String keyTag = "53fdfdc1d875625d9cffc317e9c729c1febc5849328eb15b7b75ba17eb17e70c";
            CreateCustomKeyRequestBody body = new CreateCustomKeyRequestBody();
            body.setRequestPlainKey(true); // Required parameter
            body.setBits(512); // Optional parameter
        
            try {
                api.keyTagCreateCustomKeyPost(keyTag, body);
                // Handler Successful response
            } catch (ApiException e) {
                // Handler Failed response
                e.printStackTrace();
            } catch (SdkException e) {
                // Handle exceptions that occurred before communication with the server
                e.printStackTrace();
            }
        }
        
    • 재암호화

      • 호출 방법은 다음과 같습니다.
        Re-encrypt 참조
      • 호출 예제는 다음과 같습니다.
        public void keyTagReencryptPostTest() throws ApiException, SdkException {
            String keyTag = "53fdfdc1d875625d9cffc317e9c729c1febc5849328eb15b7b75ba17eb17e70c";
            ReencryptRequestBody body = new ReencryptRequestBody();
            String ciphertext = "ncpkms:v1:eEEYwgBf/HGmqUEbTV/rASoJjneBjII+dOTnFYVOlvTnyw/+SFjwvjHpUg==";
            body.setCiphertext(ciphertext);
        
            try {
                api.keyTagReencryptPost(keyTag, body);
                // Handler Successful response
            } catch (ApiException e) {
                // Handler Failed response
                e.printStackTrace();
            } catch (SdkException e) {
                // Handle exceptions that occurred before communication with the server
                e.printStackTrace();
            }
        }
        
    • 서명

      • 호출 방법은 다음과 같습니다.
        Sign 참조
      • 호출 예제는 다음과 같습니다.
        public void keyTagSignPostTest() throws ApiException, SdkException {
            String keyTag = "4f81e47fae0a28dd50b9e5e0c3a204e371afa6d35b78b81cf802b80a2aa780ab";
            SignRequestBody body = new SignRequestBody();
            String data = "Test message";
            body.setData(Base64.getEncoder().encodeToString(data.getBytes()));
        
            try {
                api.keyTagSignPost(keyTag, body);
                // Handler Successful response
            } catch (ApiException e) {
                // Handler Failed response
                e.printStackTrace();
            } catch (SdkException e) {
                // Handle exceptions that occurred before communication with the server
                e.printStackTrace();
            }
        }
        
    • 검증

      • 호출 방법은 다음과 같습니다.
        Verify 참조
      • 호출 예제는 다음과 같습니다.
        public void keyTagVerifyPostTest() throws ApiException, SdkException {
            String keyTag = "4f81e47fae0a28dd50b9e5e0c3a204e371afa6d35b78b81cf802b80a2aa780ab";
            VerifyRequestBody body = new VerifyRequestBody();
            String data = "Test message";
            body.setData(Base64.getEncoder().encodeToString(data.getBytes()));
            body.setSignature("ncpkms:v1:MEUCIQDkn9k3voN2ABewgCAortmV4HVDXSok9bS+DX+GDd1hzAIgcIndWRNmx5j9zjMoDk9NYF3M5kk+KvRyYBVXGREVx1E=");
        
            try {
                api.keyTagVerifyPost(keyTag, body);
                // Handler Successful response
            } catch (ApiException e) {
                // Handler Failed response
                e.printStackTrace();
            } catch (SdkException e) {
                // Handle exceptions that occurred before communication with the server
                e.printStackTrace();
            }
        }
        

    이 문서가 도움이 되었습니까?

    Changing your password will log you out immediately. Use the new password to log back in.
    First name must have atleast 2 characters. Numbers and special characters are not allowed.
    Last name must have atleast 1 characters. Numbers and special characters are not allowed.
    Enter a valid email
    Enter a valid password
    Your profile has been successfully updated.