【问题标题】:Python - Decrypt S3 image file, encrypted with CSE KMSPython - 解密 S3 图像文件,使用 CSE KMS 加密
【发布时间】:2019-03-07 02:10:26
【问题描述】:

有没有办法在 Python 中解密 jpg 或 png 文件,这些文件是使用 JAVA - AmazonS3EncryptionClient 加密的 CSE KMS 并存储在 S3 中的?看起来 boto3 和 aws 加密客户端只支持密文而不支持文件。

我尝试了下面的代码,但它失败了,

def get_decrypted_stream(s3_object):
  region_name = 'us-east-1'
  encryptedImageBytes = s3_object.get()['Body'].read() 
  print("Decoded file : {}".format(encryptedImageBytes))

  client = boto3.client('kms', region_name=region_name)
  response = client.decrypt( CiphertextBlob=encryptedImageBytes)

  data = meta[u'Plaintext']
  return io.BytesIO(data)

错误:

它在“client.decrypt(CiphertextBlob=encryptedImage)”上失败,并显示 {“errorMessage”:“调用解密操作时发生错误 (413):HTTP 内容长度超过 200000 字节。”,“errorType”:“ClientError ", }

参考资料: https://docs.aws.amazon.com/kms/latest/APIReference/API_Decrypt.htmlhttps://github.com/aws/aws-encryption-sdk-python/https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/python-example-code.htmlhttps://aws-encryption-sdk-python.readthedocs.io/en/latest/

【问题讨论】:

    标签: python amazon-web-services boto3 aws-kms


    【解决方案1】:

    根据您共享的文档,EncryptDecrypt API 被限制为最大 4k 的有效负载:https://docs.aws.amazon.com/kms/latest/APIReference/API_Encrypt.html

    当使用 KMS 密钥对文件进行编码时,其原理是生成一个对称密钥,使用对称密钥对有效负载进行编码,使用 KMS encrypt API 对对称密钥进行编码,并将加密的对称密钥存储在信封中,作为例如 S3 上的元数据。

    这是一个 S3 文件加密的代码示例:

        #
        # Generate a Data Key (encoded with my Master Key in KMS)
        #
        key = kms.generate_data_key(KeyId=MASTER_KEY_ARN,KeySpec='AES_256')
        keyPlain  = key['Plaintext']
        keyCipher = key['CiphertextBlob']
    
        #
        # Encode a file with the data key
        #
        print ("Initializing encryption engine")
        iv = ''.join(chr(random.randint(0, 0xFF)) for i in range(16))
        chunksize = 64*1024
        encryptor = AES.new(keyPlain, AES.MODE_CBC, iv)
    
        print ("KMS Plain text key = %s " % base64.b64encode(keyPlain))
        print ("KMS Encrypted key  = %s " % base64.b64encode(keyCipher))
    
        in_filename = os.path.join(DIRECTORY, FILENAME)
        out_filename = in_filename + '.enc'
        filesize = os.path.getsize(in_filename)
    
        print ("Encrypting file")
        with open(in_filename, 'rb') as infile:
            with open(out_filename, 'wb') as outfile:
                outfile.write(struct.pack('<Q', filesize))
                outfile.write(iv)
    
                chunk = infile.read(chunksize)
                while len(chunk) != 0:
                    if len(chunk) % 16 != 0:
                        chunk += ' ' * (16 - len(chunk) % 16)
                    outfile.write(encryptor.encrypt(chunk))
                    chunk = infile.read(chunksize)
    
        #
        # Store encrypted file on S3
        # Encrypted Key will be stored as meta data
        #
        print ("Storing encrypted file on S3")
        metadata = {
            "key" : base64.b64encode(keyCipher)
        }
    
        #client = boto3.client('s3', 'us-west-2')
        s3 = session.client('s3')
        transfer = S3Transfer(s3)
        transfer.upload_file(out_filename, S3_BUCKET, out_filename, extra_args={"Metadata" : metadata})
        os.remove(out_filename)
    

    以及解密的示例代码:

        #
        # Download Encrypted File and it's metadata
        #
        print ("Download file and meta data from S3")
        transfer.download_file(S3_BUCKET, out_filename, out_filename)
    
        #retrieve meta data
        import boto3
        s3 = boto3.resource('s3')
        object = s3.Object(S3_BUCKET, out_filename)
        #print object.metadata
    
        keyCipher = base64.b64decode(object.metadata['key'])
    
        #decrypt encrypted key
        print ("Decrypt ciphered key")
        key = kms.decrypt(CiphertextBlob=keyCipher)
        keyPlain = key['Plaintext']
        print ("KMS Plain text key = %s " % base64.b64encode(keyPlain))
        print ("KMS Encrypted key  = %s " % base64.b64encode(keyCipher))
    
        #
        # Decrypt the file
        #
        print("Decrypt the file")
    
        in_filename = out_filename
        out_filename = in_filename + '.jpg'
        filesize = os.path.getsize(in_filename)
    
        with open(in_filename, 'rb') as infile:
            origsize = struct.unpack('<Q', infile.read(struct.calcsize('Q')))[0]
            iv = infile.read(16)
            decryptor = AES.new(keyPlain, AES.MODE_CBC, iv)
    
            with open(out_filename, 'wb') as outfile:
                chunk = infile.read(chunksize)
                while len(chunk) != 0:
                    outfile.write(decryptor.decrypt(chunk))
                    chunk = infile.read(chunksize)
    
                outfile.truncate(origsize)
    

    【讨论】:

      猜你喜欢
      • 2019-07-24
      • 2019-09-21
      • 1970-01-01
      • 2019-09-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-02-12
      • 1970-01-01
      相关资源
      最近更新 更多