すべてのプロダクト
Search
ドキュメントセンター

Key Management Service:エンベロープ暗号化を使用したローカルデータの暗号化および復号化

最終更新日:Jan 03, 2025

Alibaba Cloud にデプロイされた IT 資産の機密情報を暗号化する必要があります。 大量のローカルデータを暗号化する必要がある場合は、Key Management Service (KMS) の暗号化API操作を呼び出してオンラインでデータキーを生成し、そのデータキーを使用してローカルデータをオフラインで暗号化できます。 この暗号化メカニズムは、エンベロープ暗号化と呼ばれます。

背景情報

エンベロープ暗号化は、以下のシナリオで使用できますが、これに限定されません。

  • ビジネスデータファイルの暗号化

  • ローカルディスクに保存されているすべてのデータの暗号化

このドキュメントでは、エンベロープ暗号化を使用してローカルファイルを暗号化および復号化する方法について説明します。

データの暗号化と復号化の仕組み

KMSを使用して顧客マスターキー (CMK) を作成し、CMKを使用してデータキーを生成し、そのデータキーを使用してローカルファイルを暗号化および復号化します。 エンベロープ暗号化は、大量のデータの暗号化と復号化に適しています。 エンベロープ暗号化の手順を次の図に示します。

  • 手順: エンベロープ暗号化 信封加密

    1. KMSコンソールで、またはCreateKey操作を呼び出してCMKを作成します。

    2. GenerateDataKey操作を呼び出して、データキーを生成します。 KMSは、データキーの平文と暗号文を返します。

    3. 平文データキーを使用してローカルファイルを暗号化し、メモリから平文データキーを削除します。

    4. 暗号文データキーと暗号化されたデータファイルを永続的なストレージデバイスまたはサービスに保存します。

  • 手順: エンベロープ復号化 信封解密

    1. ローカルファイルから暗号文データキーを取得します。

    2. KMSのDecrypt操作を呼び出して、暗号文データキーを復号します。 データキーのプレーンテキストが返されます。

    3. 平文データキーを使用してローカルファイルを復号化し、メモリから平文データキーを削除します。

暗号化および復号化API操作

次の表に示すAPIを呼び出して、ローカルデータを暗号化および復号化できます。

API 操作

説明

CreateKey

CMK を作成します。

CreateAlias

CMK のエイリアスを作成します。

GenerateDataKey

データキーを生成し、指定されたCMKを使用してデータキーを暗号化します。 KMSは、データキーの平文と暗号文を返します。

解読

GenerateDataKey操作を呼び出して生成された暗号文データキーを含む、KMSで暗号化されたデータを復号します。 CMK を指定する必要はありません。

ローカルファイルの暗号化と復号化

説明

Alibaba CloudアカウントのAccessKeyペアには、すべてのAPI操作に対する権限があります。 AccessKeyペアを使用して操作を実行することは、リスクの高い操作です。 RAMユーザーを使用してAPI操作を呼び出したり、ルーチンのO&Mを実行することを推奨します。プロジェクトコードにAccessKey IDとAccessKey Secretを保存しないことを推奨します。 そうしないと、AccessKeyペアが漏洩し、アカウントに属するすべてのリソースのセキュリティが侵害される可能性があります。

この例では、AccessKeyペアは、ID認証を実装するためにALIBABA_CLOUD_ACCESS_KEY_IDとALIBABA_CLOUD_ACCESS_KEY_SECRET環境変数に保存されます。

Alibaba Cloud CLIを使用してCMKを作成し、ローカルファイルを暗号化および復号化できます。

  1. CreateKey操作を呼び出して、CMKを作成します。

    aliyun kms CreateKey

    期待される出力:

    {
      "KeyMetadata": {
        "CreationDate": "2019-04-08T07:45:54Z",
        "Description": "",
        "KeyId": "1234abcd-12ab-34cd-56ef-12345678****",
        "KeyState": "Enabled",
        "KeyUsage": "ENCRYPT/DECRYPT",
        "DeleteDate": "",
        "Creator": "151266687691****",
        "Arn": "acs:kms:cn-hangzhou:151266687691****:key/1234abcd-12ab-34cd-56ef-12345678****",
        "Origin": "Aliyun_KMS",
        "MaterialExpireTime": ""
      },
      "RequestId": "2a37b168-9fa0-4d71-aba4-2077dd9e80df"
    }
  2. オプション。 CMKのエイリアスを作成します。

    エイリアスは、CMKを識別するためにオプションで使用されます。 CMKにエイリアスがない場合は、CMKのIDを使用してCMKを識別できます。

    aliyun kms CreateAlias --AliasName alias/Apollo/WorkKey --KeyId 1234abcd-12ab-34cd-56ef-12345678****
    説明

    この例では、Apollo/WorkKeyApolloプロジェクトのCMKのエイリアスです。 後続のサンプルコードでエイリアスalias/Apollo/WorkKeyを使用して、暗号化操作を呼び出すことができます。

  3. ローカルファイルを暗号化します。

    次のサンプルコード:

    • alias/Apollo/WorkKeyはCMKのエイリアスです。

    • . /データ /sales.csvはプレーンテキストファイルです。

    • . /data/sales.csv.cipherは返された暗号文ファイルです。

    #!/usr/bin/env python
    #coding=utf-8
    
    import json
    import base64
    
    from Crypto.Cipher import AES
    
    from aliyunsdkcore import client
    from aliyunsdkkms.request.v20160120 import GenerateDataKeyRequest
    
    def KmsGenerateDataKey(client, key_alias):
        request = GenerateDataKeyRequest.GenerateDataKeyRequest()
        request.set_accept_format('JSON')
        request.set_KeyId(key_alias)
        request.set_NumberOfBytes(32)
        response = json.loads(client.do_action(request))
    
        datakey_encrypted = response["CiphertextBlob"]
        datakey_plaintext = response["Plaintext"]
        return (datakey_plaintext, datakey_encrypted)
    
    def ReadTextFile(in_file):
      file = open(in_file, 'r')
      content = file.read()
      file.close()
      return content
    
    def WriteTextFile(out_file, lines):
      file = open(out_file, 'w')
      for ln in lines:
        file.write(ln)
        file.write('\n')
      file.close()
    
    # Out file format (text)
    # Line 1: b64 encoded data key
    # Line 2: b64 encoded IV
    # Line 3: b64 encoded ciphertext
    # Line 4: b64 encoded authentication tag
    def LocalEncrypt(datakey_plaintext, datakey_encrypted, in_file, out_file):
      data_key_binary = base64.b64decode(datakey_plaintext)
      cipher = AES.new(data_key_binary, AES.MODE_EAX)
    
      in_content = ReadTextFile(in_file)
      ciphertext, tag = cipher.encrypt_and_digest(in_content)
    
      lines = [datakey_encrypted, base64.b64encode(cipher.nonce), base64.b64encode(ciphertext), base64.b64encode(tag)];
      WriteTextFile(out_file, lines)
    
    clt = client.AcsClient(os.getenv("ALIBABA_CLOUD_ACCESS_KEY_ID"),os.getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET"),'Region-Id')
    
    key_alias = 'alias/Apollo/WorkKey'
    
    in_file = './data/sales.csv'
    out_file = './data/sales.csv.cipher'
    
    # Generate Data Key
    datakey = KmsGenerateDataKey(clt, key_alias)
    
    # Locally Encrypt the sales record
    LocalEncrypt(datakey[0], datakey[1], in_file, out_file)
  4. ローカルファイルを复号化します。

    次のサンプルコード:

    • . /data/sales.csv.cipherは暗号化ファイルです。

    • . /data/decrypted_sales.csvは返された平文ファイルです。

    #!/usr/bin/env python
    #coding=utf-8
    
    import json
    import base64
    
    from Crypto.Cipher import AES
    
    from aliyunsdkcore import client
    from aliyunsdkkms.request.v20160120 import DecryptRequest
    
    def KmsDecrypt(client, ciphertext):
      request = DecryptRequest.DecryptRequest()
      request.set_accept_format('JSON')
      request.set_CiphertextBlob(ciphertext)
      response = json.loads(client.do_action(request))
      return response.get("Plaintext")
    
    def ReadTextFile(in_file):
      file = open(in_file, 'r')
      lines = []
      for ln in file:
        lines.append(ln)
      file.close()
      return lines
    
    def WriteTextFile(out_file, content):
      file = open(out_file, 'w')
      file.write(content)
      file.close()
    
    def LocalDecrypt(datakey, iv, ciphertext, tag, out_file):
      cipher = AES.new(datakey, AES.MODE_EAX, iv)
      data = cipher.decrypt_and_verify(ciphertext, tag).decode('utf-8')
      WriteTextFile(out_file, data)
    
    clt = client.AcsClient(os.getenv("ALIBABA_CLOUD_ACCESS_KEY_ID"),os.getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET"),'Region-Id')
    
    in_file = './data/sales.csv.cipher'
    out_file = './data/decrypted_sales.csv'
    
    # Read encrypted file
    in_lines = ReadTextFile(in_file)
    
    # Decrypt data key
    datakey = KmsDecrypt(clt, in_lines[0])
    
    # Locally decrypt the sales record
    LocalDecrypt(
      base64.b64decode(datakey),
      base64.b64decode(in_lines[1]), # IV
      base64.b64decode(in_lines[2]), # Ciphertext
      base64.b64decode(in_lines[3]), # Authentication tag
      out_file
      )