Key Management Service 키를 활용한 암호화 예제
Key Management Service 키를 활용한 암호화 예제
KMS에서 생성한 키를 사용하여 봉투 암호화(Envelope Encryption) 및 데이터 서명/검증을 구현하기 위한 Java 코드 예제입니다.
봉투 암호화
봉투 암호화 시나리오를 제시하고 시나리오에 따라 작성된 Java, Go, Python 예제 코드와 결과값을 확인할 수 있습니다.
시나리오
- 비밀번호 정보를 봉투 암호화 방식으로 암호화하기 위해 Data Key를 발급 받습니다.
- 발급 받은 Data Key 정보를 사용해 비밀번호를 암호화합니다.
- 암호화된 비밀번호, 암호화된 Data Key 정보를 봉투 암호화하여 JSON 파일로 저장합니다.
Java 예제 코드
제시된 시나리오에 따라 작성된 Java 예제 코드입니다.
// URI
static String KMS_API_BASE_URI = {{ OpenAPI 가이드의 URL 참조 }};
// END POINT
static String KMS_API_DECRYPT = "/v1/kms/openapi/decrypt/%s";
static String KMS_API_CREATE_DATAKEY = "/v1/kms/openapi/datakey/%s";
// KEY ID
static String KEY_ID = {{마스터 키 ID}};
createEnvelop() {
// 새로운 데이터 키 생성을 요청
String encryptedDataKey = getDataKey();
// 암호화를 할 데이터
String example_json_data = "{\"PASSWORD\":\"SECRET_CREDENTIAL\"}";
// 암호화된 데이터 봉투(Envelop encryption)
String envelope = encryptData(example_json_data, encryptedDataKey);
// 이 예제 코드에서는 암호화된 데이터 봉투를 파일로 저장
File envelopeFile = new File("envelope.json");
}
getDataKey() {
String endPoint = String.format(KMS_API_CREATE_DATAKEY, KEY_ID);
String url = KMS_API_BASE_URI + endPoint;
JSONObject data = new JSONObject();
data.put("key_type", "plaintext");
JSONObject respJsonObject = callApi(endPoint, data.toJSONString());
return respJsonObject.get("ciphertext").toString();
}
encryptData() {
Map<String, String> envelope = new HashMap<>();
// 데이터 키 복호화
String dataKey = decryptDataKey(encryptedDataKey);
// 생성된 데이터 키를 AES-CBC 방식으로 암호화
// Cipher Class 사용 (사용자가 기 사용 중인 암호화 알고리즘 사용 가능)
SecretKey secretKey = new SecretKeySpec(decodeBase64(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("encryptedKey", encryptedDataKey);
envelope.put("cipherText", encodeBase64(cipherText));
envelope.put("iv", encodeBase64(iv));
return JSONValue.toJSONString(envelope);
}
decryptDataKey() {
String endPoint = String.format(KMS_API_DECRYPT, KEY_ID);
JSONObject data = new JSONObject();
data.put("cipherText", sealedKey);
JSONObject respJsonObject = callApi(endPoint, data.toJSONString());
String plaintext = (respJsonObject.get("plaintext")).toString();
return plaintext;
}
Go 예제 코드
제시된 시나리오에 따라 작성된 Go 예제 코드입니다.
// URI
const KMS_API_BASE_URI = {{ OpenAPI 가이드의 URL 참조 }}
// END POINT
const KMS_API_DECRYPT = "/v1/kms/openapi/decrypt/%s"
const KMS_API_CREATE_DATAKEY = "/v1/kms/openapi/datakey/%s"
// KEY ID
const KEY_ID = {{마스터 키 ID}}
createEnvelop() {
// 새로운 데이터 키 생성을 요청
encryptedDataKey := getDataKey()
// 암호화를 할 데이터
example_json_data := "{\"PASSWORD\":\"SECRET_CREDENTIAL\"}"
// 암호화된 데이터 봉투(Envelop encryption)
envelope := encryptData(example_json_data, encryptedDataKey)
// 이 예제 코드에서는 암호화된 데이터 봉투를 파일로 저장
file, _ := os.Create("envelope.json")
defer file.Close()
file.WriteString(envelope)
}
getDataKey() {
endPoint := fmt.Sprintf(KMS_API_CREATE_DATAKEY, KEY_ID)
data := map[string]interface{}{
"key_type": "plaintext",
}
jsonData, _ := json.Marshal(data)
respJsonObject := callApi(endPoint, jsonData)
info := &KMSDatakeyInfo{}
json.Unmarshal([]byte(respJsonObject), info)
return info.DataKey
}
encryptData() {
envelope := make(map[string]string)
// 데이터 키 복호화
dataKey := decryptDataKey(encryptedDataKey)
secretKey, _ := base64.StdEncoding.DecodeString(dataKey)
// 생성된 데이터 키를 AES-CBC 방식으로 암호화
// Cipher Class 사용
block, _ := aes.NewCipher(secretKey)
cipherText := make([]byte, aes.BlockSize+len(example_json_data))
iv := cipherText[:aes.BlockSize]
if _, err := io.ReadFull(rand.Reader, iv); err != nil {
panic(err)
}
mode := cipher.NewCFBEncrypter(block, iv)
mode.XORKeyStream(cipherText[aes.BlockSize:], []byte(example_json_data))
envelope["encryptedKey"] = encryptedDataKey
envelope["cipherText"] = base64.StdEncoding.EncodeToString(cipherText)
envelope["iv"] = base64.StdEncoding.EncodeToString(iv)
jsonString, _ := json.Marshal(envelope)
return string(jsonString)
}
decryptDataKey() {
endPoint := fmt.Sprintf(KMS_API_DECRYPT, KEY_ID)
data := map[string]interface{}{
"cipherText": sealedKey,
}
jsonData, _ := json.Marshal(data)
respJsonObject := callApi(endPoint, jsonData)
info := &KMSDecryptInfo{}
json.Unmarshal([]byte(respJsonObject), info)
return info.DecryptedData
}
Python 예제 코드
제시된 시나리오에 따라 작성된 Python 예제 코드입니다.
# URI
KMS_API_BASE_URI = {{ OpenAPI 가이드의 URL 참조 }}
# END POINT
KMS_API_DECRYPT = "/v1/kms/openapi/decrypt/"
KMS_API_CREATE_DATAKEY = "/v1/kms/openapi/datakey/"
# KEY ID
KEY_ID = {{마스터 키 ID}}
create_envelop()
# 새로운 데이터 키 생성을 요청
encrypted_data_key = get_dataKey()
# 암호화를 할 데이터
example_json_data = {"PASSWORDTEST":"SECRET_CREDENTIALTEST"}
json_data_str = json.dumps(example_json_data)
# 암호화된 데이터 봉투(Envelop encryption)
envelope = encrypt_data(json_data_str,encrypted_data_key)
# 이 예제 코드에서는 암호화된 데이터 봉투를 파일로 저장
with open("envelope.json", "w") as file:
file.write(envelope)
get_dataKey()
end_point = f"{KMS_API_CREATE_DATAKEY}{KEY_ID}"
data = {
"key_type": "plaintext"
}
response_object = call_api(end_point, data)
data_key = response_object.get("ciphertext", "")
return data_key
encrypt_data()
envelope = {}
# 데이터 키 복호화
dataKey = decrypt_data_key(encrypted_data_key)
decoded_data_key = base64.b64decode(dataKey)
# 생성된 데이터 키를 AES-CBC 방식으로 암호화
# Cipher Class 사용
iv = get_random_bytes(16)
cipher = AES.new(decoded_data_key, AES.MODE_CBC, iv)
data_to_encrypt = obj
data_bytes = data_to_encrypt.encode()
padded_data = pad(data_bytes, AES.block_size)
cipher_text = cipher.encrypt(padded_data).hex()
envelope["encryptedKey"] = encrypted_data_key
envelope["cipherText"] = cipher_text
envelope["iv"] = base64.b64encode(iv).decode()
return json.dumps(envelope)
decrypt_data_key()
end_point = f"{KMS_API_DECRYPT}{KEY_ID}"
data = {}
data["cipherText"] = sealed_key
resp_json_object = call_api(end_point,data)
plaintext = resp_json_object.get("decryptedData")
return plaintext
예제 코드 결과값
예제 코드의 결과값을 표시합니다.
{
"cipherText":"d3S81rzaGAl8U12LlKSlRbDekPlGuibTntXX962KCjBIKuXdPOG8N8vk3Jet8lyG",
"iv":"0kP7QKZ6BUeQPlThk4tySA==",
"encryptedKey":"vault:v1:KJjjLtGHTbaV5N8LWC5O9eMDCaJVeff5SM\/MAYseugjiqiXFVgdXaKXg6kym0NmjHkO\/wLPsa+YK0aVk"
}
봉투 암호화 사용
봉투 암호화 사용 시나리오를 제시하고 시나리오에 따라 작성된 Java, Go, Python 예제 코드와 결과값을 확인할 수 있습니다.
시나리오
- 암호화된 봉투 파일의 Data Key를 복호화합니다.
- 복호화된 Data Key로 봉투 파일의 암호화 데이터를 복호화합니다.
Java 예제 코드
제시된 시나리오에 따라 작성된 Java 예제 코드입니다.
// URI
static String KMS_API_BASE_URI = {{ OpenAPI 가이드의 URL 참조 }};
// END POINT
static String KMS_API_DECRYPT = "/v1/kms/openapi/decrypt/%s";
// KEY ID
static String KEY_ID = {{마스터 키 ID}};;
getData() {
// 암호화된 데이터 봉투(Envelop encryption)
String envelope = new String(Files.readAllBytes(Paths.get("envelope.json")));
JSONParser parser = new JSONParser();
JSONObject envelopeJson = (JSONObject) parser.parse(envelope);
String encryptedDataKey = envelopeJson.get("encryptedKey").toString();
String cipherText = envelopeJson.get("cipherText").toString();
String iv = envelopeJson.get("iv").toString();
return decryptData(cipherText, encryptedDataKey, iv);
}
decryptData() {
String dataKey = decryptDataKey(encryptedDataKey);
IvParameterSpec ivParameterSpec = new IvParameterSpec(decodeBase64(iv));
SecretKey secretKey = new SecretKeySpec(decodeBase64(dataKey), "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, secretKey, ivParameterSpec);
byte[] plaintext = cipher.doFinal(decodeBase64(cipherText));
return new String(plaintext);
}
decryptDataKey() {
String endPoint = String.format(KMS_API_DECRYPT, KEY_ID);
JSONObject data = new JSONObject();
data.put("cipherText", sealedKey);
JSONObject respJsonObject = callApi(endPoint, data.toJSONString());
String plaintext = (respJsonObject.get("plaintext")).toString();
return plaintext;
}
Go 예제 코드
제시된 시나리오에 따라 작성된 Go 예제 코드입니다.
// URI
const KMS_API_BASE_URI = {{ OpenAPI 가이드의 URL 참조 }}
// END POINT
const KMS_API_DECRYPT = "/v1/kms/openapi/decrypt/%s"
// KEY ID
const KEY_ID = {{마스터 키 ID}}
getData() {
// 암호화된 데이터 봉투(Envelop encryption) 불러오기
jsonData, _ := os.ReadFile("envelope.json")
var envelope map[string]interface{}
if err := json.Unmarshal(jsonData, &envelope); err != nil {
fmt.Println("JSON 파싱 오류:", err)
os.Exit(1)
}
encryptedDataKey := envelope["encryptedKey"].(string)
cipherText := envelope["cipherText"].(string)
iv := envelope["iv"].(string)
return decryptData(cipherText, encryptedDataKey, iv)
}
decryptData() {
dataKey := decryptDataKey(encryptedDataKey)
ciphertext, _ := base64.StdEncoding.DecodeString(cipherText)
dataKeyBytes, _ := base64.StdEncoding.DecodeString(dataKey)
decodedData := ciphertext[aes.BlockSize:]
ivparam := ciphertext[:aes.BlockSize]
block, _ := aes.NewCipher(dataKeyBytes)
mode := cipher.NewCFBDecrypter(block, ivparam)
mode.XORKeyStream(decodedData, decodedData)
decryptedData := string(decodedData)
return decryptedData
}
decryptDataKey() {
endPoint := fmt.Sprintf(KMS_API_DECRYPT, KEY_ID)
data := map[string]interface{}{
"cipherText": sealedKey,
}
jsonData, _ := json.Marshal(data)
respJsonObject := callApi(endPoint, jsonData)
info := &KMSDecryptInfo{}
json.Unmarshal([]byte(respJsonObject), info)
return info.DecryptedData
}
Python 예제 코드
제시된 시나리오에 따라 작성된 Python 예제 코드입니다.
# URI
KMS_API_BASE_URI = {{ OpenAPI 가이드의 URL 참조 }}
# END POINT
KMS_API_DECRYPT = "/v1/kms/openapi/decrypt/"
# KEY ID
KEY_ID = {{마스터 키 ID}}
get_data()
# 암호화된 데이터 봉투(Envelop encryption) 열기
with open("envelope.json", "r") as file:
envelope = file.read()
envelope_json = json.loads(envelope)
encrypted_data_key = envelope_json["encryptedKey"]
cipher_text = envelope_json["cipherText"]
iv = envelope_json["iv"]
return decrypt_data(cipher_text, encrypted_data_key, iv)
decrypt_data()
data_key = decrypt_data_key(encrypted_data_key)
iv_bytes = base64.b64decode(iv)
decoded_data_key = base64.b64decode(data_key)
cipher_txt = bytes.fromhex(cipher_text)
cipher = AES.new(decoded_data_key, AES.MODE_CBC, iv_bytes)
plain_text_bytes = unpad(cipher.decrypt(cipher_txt), AES.block_size)
plain_text = plain_text_bytes.decode('utf-8')
return plain_text
decrypt_data_key()
end_point = f"{KMS_API_DECRYPT}{KEY_ID}"
data = {}
data["cipherText"] = sealed_key
resp_json_object = call_api(end_point,data)
plaintext = resp_json_object.get("decryptedData")
return plaintext
예제 코드 결과값
예제 코드의 결과값을 표시합니다.
{"PASSWORD":"SECRET_CREDENTIAL"}
데이터 서명 사용
데이터의 무결성을 보증하기 위한 데이터 서명 사용 시나리오를 제시하고 시나리오에 따라 작성된 Java, Go, Python 예제 코드와 결과값을 확인할 수 있습니다.
시나리오
- 서명할 데이터를 OpenAPI로 호출하여 서명합니다.
- 서명된 데이터는 봉투화하여 json 파일로 저장합니다.
Java 예제 코드
제시된 시나리오에 따라 작성된 Java 예제 코드입니다.
// URI
static String KMS_API_BASE_URI = {{ OpenAPI 가이드의 URL 참조 }};
// END POINT
static String KMS_API_SIGN = "/v1/kms/openapi/sign/%s";
// KEY ID
static String KEY_ID = {{마스터 키 ID}};
signEnvelop() {
// 서명 데이터 봉투(Envelop encryption)
String envelope = sign();
// 이 예제 코드에서는 서명 데이터 봉투를 파일로 저장
File envelopeFile = new File("signEnvelope.json");
OutputStream os = new BufferedOutputStream(new FileOutputStream(envelopeFile));
try {
os.write(envelope.getBytes());
} finally {
os.close();
}
}
sign() {
Map<String, String> envelope = new HashMap<>();
String example_credential = "SCP KMS Sign Test!!!";
String endPoint = String.format(KMS_API_SIGN, KEY_ID);
JSONObject data = new JSONObject();
data.put("input", encodeToBase64(example_credential));
JSONObject respJsonObject = callApi(endPoint, data.toJSONString());
envelope.put("signature", respJsonObject.get("signature").toString());
if(respJsonObject.get("batch_results") != null) {
envelope.put("batch_results", respJsonObject.get("batch_results").toString());
}
return JSONValue.toJSONString(envelope);
}
Go 예제 코드
제시된 시나리오에 따라 작성된 Go 예제 코드입니다.
// URI
const KMS_API_BASE_URI = {{ OpenAPI 가이드의 URL 참조 }}
// END POINT
const KMS_API_SIGN = "/v1/kms/openapi/sign/%s"
// KEY ID
const KEY_ID = {{마스터 키 ID}}
signEnvelop() {
// 서명 데이터 봉투(Envelop encryption)
envelope := sign()
// 이 예제 코드에서는 서명 데이터 봉투를 파일로 저장
file, _ := os.Create("signEnvelope.json")
defer file.Close()
file.WriteString(envelope)
}
sign() {
envelope := make(map[string]string)
example_credential := "SCP KMS Sign Test!!!"
endPoint := fmt.Sprintf(KMS_API_SIGN, KEY_ID)
data := map[string]interface{}{
"input": base64.StdEncoding.EncodeToString([]byte(example_credential)),
}
jsonData, _ := json.Marshal(data)
respJsonObject := callApi(endPoint, jsonData)
info := &KMSSignInfo{}
json.Unmarshal([]byte(respJsonObject), info)
envelope["signature"] = info.Signature
jsonString, _ := json.Marshal(envelope)
return string(jsonString)
}
Python 예제 코드
제시된 시나리오에 따라 작성된 Python 예제 코드입니다.
# URI
KMS_API_BASE_URI = {{ OpenAPI 가이드의 URL 참조 }}
# END POINT
KMS_API_SIGN = "/v1/kms/openapi/sign/"
# KEY ID
KEY_ID = {{마스터 키 ID}}
sign_envelop()
# 서명 데이터 봉투(Envelop encryption)
envelope = sign()
# 이 예제 코드에서는 서명 데이터 봉투를 파일로 저장
with open("signEnvelope.json", "w") as file:
file.write(envelope)
sign()
envelope = {}
example_credential = "SCP KMS Sign Test!!!"
end_point = f"{KMS_API_SIGN}{KEY_ID}"
credential_bytes = example_credential.encode('utf-8')
data = {
"input": base64.b64encode(credential_bytes).decode('utf-8')
}
resp_json_object = call_api(end_point,data)
envelope["signature"] = resp_json_object.get("signature")
return json.dumps(envelope)
예제 코드 결과값
예제 코드의 결과값을 표시합니다.
{
"signature":"vault:v1:qHGf4ALkTao1Yy\/lpSbLQ2l8YVpsHWBP6ic3Ux1BKSodQQxnEIrjPyUwXXQ1NZfGSVxdeVe5Y6kb0nUPNADQpzkOh9\/e8T\/QCOs9==",
"projectId":"PROJECT-qWrHRJX5sZnTkopcr9N1dk"
}
데이터 검증 사용
데이터의 무결성을 검증하기 위한 검증 사용 시나리오를 제시하고 시나리오에 따라 작성된 Java, Go, Python 예제 코드와 결과값을 확인할 수 있습니다.
시나리오
- 서명된 봉투 파일의 서명값을 가져옵니다.
- 서명된 데이터를 검증하여 결과값을 출력합니다.
Java 예제 코드
제시된 시나리오에 따라 작성된 Java 예제 코드입니다.
// URI
static String KMS_API_BASE_URI = {{ OpenAPI 가이드의 URL 참조 }};
// END POINT
static String KMS_API_VERIFY = "/v1/kms/openapi/verify/%s";
// KEY ID
static String KEY_ID = {{마스터 키 ID}};
getSign() {
// 서명 데이터 봉투(Envelop encryption)
String envelope = new String(Files.readAllBytes(Paths.get("signEnvelope.json")));
JSONParser parser = new JSONParser();
JSONObject envelopeJson = (JSONObject) parser.parse(envelope);
String signature = envelopeJson.get("signature").toString();
return verify(signature);
}
verify() {
String endPoint = String.format(KMS_API_VERIFY, KEY_ID);
JSONObject data = new JSONObject();
data.put("input", "U0NQIEtNUyBTaWduIFRlc3QhISE=");
data.put("signature", signature);
JSONObject respJsonObject = callApi(endPoint, data.toJSONString());
String valid = (respJsonObject.get("valid")).toString();
return valid;
}
Go 예제 코드
제시된 시나리오에 따라 작성된 Go 예제 코드입니다.
// URI
const KMS_API_BASE_URI = {{ OpenAPI 가이드의 URL 참조 }}
// END POINT
const KMS_API_VERIFY = "/v1/kms/openapi/verify/%s"
// KEY ID
const KEY_ID = {{마스터 키 ID}}
getSign() {
// 서명 데이터 봉투(Envelop encryption) 불러오기
jsonData, _ := os.ReadFile("signEnvelope.json")
var envelope map[string]interface{}
if err := json.Unmarshal(jsonData, &envelope); err != nil {
fmt.Println("JSON 파싱 오류:", err)
os.Exit(1)
}
signature := envelope["signature"].(string)
return verify(signature)
}
verify() {
endPoint := fmt.Sprintf(KMS_API_VERIFY, KEY_ID)
data := map[string]interface{}{
"input": "U0NQIEtNUyBTaWduIFRlc3QhISE=",
"signature": signature,
}
jsonData, _ := json.Marshal(data)
respJsonObject := callApi(endPoint, jsonData)
info := &KMSVerifyInfo{}
json.Unmarshal([]byte(respJsonObject), info)
return info.Valid
}
Python 예제 코드
제시된 시나리오에 따라 작성된 Python 예제 코드입니다.
# URI
KMS_API_BASE_URI = {{ OpenAPI 가이드의 URL 참조 }}
# END POINT
KMS_API_VERIFY = "/v1/kms/openapi/verify/"
# KEY ID
KEY_ID = {{마스터 키 ID}}
get_sign()
# 서명 데이터 봉투(Envelop encryption) 열기
with open("signEnvelope.json", "r") as file:
envelope = file.read()
envelope_json = json.loads(envelope)
signature = envelope_json["signature"]
return verify(signature)
verify()
end_point = f"{KMS_API_VERIFY}{KEY_ID}"
data = {
"input": "U0NQIEtNUyBTaWduIFRlc3QhISE=",
"signature": signature
}
resp_json_object = call_api(end_point,data)
valid = resp_json_object.get("valid")
return valid
예제 코드 결과값
예제 코드의 결과값을 표시합니다.
{
"valid": true
}