| 1 | efrain | 1 | <?php
 | 
        
           |  |  | 2 | namespace Aws\Crypto;
 | 
        
           |  |  | 3 |   | 
        
           |  |  | 4 | use Aws\Kms\KmsClient;
 | 
        
           |  |  | 5 |   | 
        
           |  |  | 6 | /**
 | 
        
           |  |  | 7 |  * Uses KMS to supply materials for encrypting and decrypting data.
 | 
        
           |  |  | 8 |  *
 | 
        
           |  |  | 9 |  * Legacy implementation that supports legacy S3EncryptionClient and
 | 
        
           |  |  | 10 |  * S3EncryptionMultipartUploader, which use an older encryption workflow. Use
 | 
        
           |  |  | 11 |  * KmsMaterialsProviderV2 with S3EncryptionClientV2 or
 | 
        
           |  |  | 12 |  * S3EncryptionMultipartUploaderV2 if possible.
 | 
        
           |  |  | 13 |  *
 | 
        
           |  |  | 14 |  * @deprecated
 | 
        
           |  |  | 15 |  */
 | 
        
           |  |  | 16 | class KmsMaterialsProvider extends MaterialsProvider implements MaterialsProviderInterface
 | 
        
           |  |  | 17 | {
 | 
        
           |  |  | 18 |     const WRAP_ALGORITHM_NAME = 'kms';
 | 
        
           |  |  | 19 |   | 
        
           |  |  | 20 |     private $kmsClient;
 | 
        
           |  |  | 21 |     private $kmsKeyId;
 | 
        
           |  |  | 22 |   | 
        
           |  |  | 23 |     /**
 | 
        
           |  |  | 24 |      * @param KmsClient $kmsClient A KMS Client for use encrypting and
 | 
        
           |  |  | 25 |      *                             decrypting keys.
 | 
        
           |  |  | 26 |      * @param string $kmsKeyId The private KMS key id to be used for encrypting
 | 
        
           |  |  | 27 |      *                         and decrypting keys.
 | 
        
           |  |  | 28 |      */
 | 
        
           |  |  | 29 |     public function __construct(
 | 
        
           |  |  | 30 |         KmsClient $kmsClient,
 | 
        
           |  |  | 31 |         $kmsKeyId = null
 | 
        
           |  |  | 32 |     ) {
 | 
        
           |  |  | 33 |         $this->kmsClient = $kmsClient;
 | 
        
           |  |  | 34 |         $this->kmsKeyId = $kmsKeyId;
 | 
        
           |  |  | 35 |     }
 | 
        
           |  |  | 36 |   | 
        
           |  |  | 37 |     public function fromDecryptionEnvelope(MetadataEnvelope $envelope)
 | 
        
           |  |  | 38 |     {
 | 
        
           |  |  | 39 |         if (empty($envelope[MetadataEnvelope::MATERIALS_DESCRIPTION_HEADER])) {
 | 
        
           |  |  | 40 |             throw new \RuntimeException('Not able to detect the materials description.');
 | 
        
           |  |  | 41 |         }
 | 
        
           |  |  | 42 |   | 
        
           |  |  | 43 |         $materialsDescription = json_decode(
 | 
        
           |  |  | 44 |             $envelope[MetadataEnvelope::MATERIALS_DESCRIPTION_HEADER],
 | 
        
           |  |  | 45 |             true
 | 
        
           |  |  | 46 |         );
 | 
        
           |  |  | 47 |   | 
        
           |  |  | 48 |         if (empty($materialsDescription['kms_cmk_id'])
 | 
        
           |  |  | 49 |             && empty($materialsDescription['aws:x-amz-cek-alg'])) {
 | 
        
           |  |  | 50 |             throw new \RuntimeException('Not able to detect kms_cmk_id (legacy'
 | 
        
           |  |  | 51 |                 . ' implementation) or aws:x-amz-cek-alg (current implementation)'
 | 
        
           |  |  | 52 |                 . ' from kms materials description.');
 | 
        
           |  |  | 53 |         }
 | 
        
           |  |  | 54 |   | 
        
           |  |  | 55 |         return new self(
 | 
        
           |  |  | 56 |             $this->kmsClient,
 | 
        
           |  |  | 57 |             isset($materialsDescription['kms_cmk_id'])
 | 
        
           |  |  | 58 |                 ? $materialsDescription['kms_cmk_id']
 | 
        
           |  |  | 59 |                 : null
 | 
        
           |  |  | 60 |         );
 | 
        
           |  |  | 61 |     }
 | 
        
           |  |  | 62 |   | 
        
           |  |  | 63 |     /**
 | 
        
           |  |  | 64 |      * The KMS key id for use in matching this Provider to its keys,
 | 
        
           |  |  | 65 |      * consistently with other SDKs as 'kms_cmk_id'.
 | 
        
           |  |  | 66 |      *
 | 
        
           |  |  | 67 |      * @return array
 | 
        
           |  |  | 68 |      */
 | 
        
           |  |  | 69 |     public function getMaterialsDescription()
 | 
        
           |  |  | 70 |     {
 | 
        
           |  |  | 71 |         return ['kms_cmk_id' => $this->kmsKeyId];
 | 
        
           |  |  | 72 |     }
 | 
        
           |  |  | 73 |   | 
        
           |  |  | 74 |     public function getWrapAlgorithmName()
 | 
        
           |  |  | 75 |     {
 | 
        
           |  |  | 76 |         return self::WRAP_ALGORITHM_NAME;
 | 
        
           |  |  | 77 |     }
 | 
        
           |  |  | 78 |   | 
        
           |  |  | 79 |     /**
 | 
        
           |  |  | 80 |      * Takes a content encryption key (CEK) and description to return an encrypted
 | 
        
           |  |  | 81 |      * key by using KMS' Encrypt API.
 | 
        
           |  |  | 82 |      *
 | 
        
           |  |  | 83 |      * @param string $unencryptedCek Key for use in encrypting other data
 | 
        
           |  |  | 84 |      *                               that itself needs to be encrypted by the
 | 
        
           |  |  | 85 |      *                               Provider.
 | 
        
           |  |  | 86 |      * @param string $materialDescription Material Description for use in
 | 
        
           |  |  | 87 |      *                                    encrypting the $cek.
 | 
        
           |  |  | 88 |      *
 | 
        
           |  |  | 89 |      * @return string
 | 
        
           |  |  | 90 |      */
 | 
        
           |  |  | 91 |     public function encryptCek($unencryptedCek, $materialDescription)
 | 
        
           |  |  | 92 |     {
 | 
        
           |  |  | 93 |         $encryptedDataKey = $this->kmsClient->encrypt([
 | 
        
           |  |  | 94 |             'Plaintext' => $unencryptedCek,
 | 
        
           |  |  | 95 |             'KeyId' => $this->kmsKeyId,
 | 
        
           |  |  | 96 |             'EncryptionContext' => $materialDescription
 | 
        
           |  |  | 97 |         ]);
 | 
        
           |  |  | 98 |         return base64_encode($encryptedDataKey['CiphertextBlob']);
 | 
        
           |  |  | 99 |     }
 | 
        
           |  |  | 100 |   | 
        
           |  |  | 101 |     /**
 | 
        
           |  |  | 102 |      * Takes an encrypted content encryption key (CEK) and material description
 | 
        
           |  |  | 103 |      * for use decrypting the key by using KMS' Decrypt API.
 | 
        
           |  |  | 104 |      *
 | 
        
           |  |  | 105 |      * @param string $encryptedCek Encrypted key to be decrypted by the Provider
 | 
        
           |  |  | 106 |      *                             for use decrypting other data.
 | 
        
           |  |  | 107 |      * @param string $materialDescription Material Description for use in
 | 
        
           |  |  | 108 |      *                                    encrypting the $cek.
 | 
        
           |  |  | 109 |      *
 | 
        
           |  |  | 110 |      * @return string
 | 
        
           |  |  | 111 |      */
 | 
        
           |  |  | 112 |     public function decryptCek($encryptedCek, $materialDescription)
 | 
        
           |  |  | 113 |     {
 | 
        
           |  |  | 114 |         $result = $this->kmsClient->decrypt([
 | 
        
           |  |  | 115 |             'CiphertextBlob' => $encryptedCek,
 | 
        
           |  |  | 116 |             'EncryptionContext' => $materialDescription
 | 
        
           |  |  | 117 |         ]);
 | 
        
           |  |  | 118 |   | 
        
           |  |  | 119 |         return $result['Plaintext'];
 | 
        
           |  |  | 120 |     }
 | 
        
           |  |  | 121 | }
 |