Пример #1
0
 public function getObjectSecurely($args = array())
 {
     $meta = $this->ks3client->getObjectMeta($args);
     if (isset($meta["UserMeta"]["x-kss-meta-x-kss-key"]) && isset($meta["UserMeta"]["x-kss-meta-x-kss-iv"])) {
         $encryptedInMeta = TRUE;
     } else {
         $encryptedInMeta = FALSE;
     }
     $encrypted = TRUE;
     $encryptionInfo = array();
     if ($encryptedInMeta) {
         $encryptionInfo["iv"] = base64_decode($meta["UserMeta"]["x-kss-meta-x-kss-iv"]);
         $matdesc = $meta["UserMeta"]["x-kss-meta-x-kss-matdesc"];
         $encryptionInfo["matdesc"] = $matdesc;
         $cekEncrypted = base64_decode($meta["UserMeta"]["x-kss-meta-x-kss-key"]);
         $encryptionInfo["cek"] = $cek = EncryptionUtil::decodeCek($this->encryptionMaterials, $cekEncrypted);
     } else {
         if ($this->ks3client->objectExists(array("Bucket" => $args["Bucket"], "Key" => $args["Key"] . EncryptionUtil::$INSTRUCTION_SUFFIX))) {
             $insKey = $args["Key"] . EncryptionUtil::$INSTRUCTION_SUFFIX;
             $getIns = array("Bucket" => $args["Bucket"], "Key" => $insKey);
             $s3Object = $this->ks3client->getObject($getIns);
             if (!EncryptionUtil::isInstructionFile($s3Object)) {
                 throw new Ks3ClientException($insKey . " is not an InstructionFile");
             }
             $content = $s3Object["Content"];
             $content = json_decode($content, TRUE);
             $encryptionInfo["iv"] = base64_decode($content["x-kss-iv"]);
             $matdesc = $content["x-kss-matdesc"];
             $encryptionInfo["matdesc"] = $matdesc;
             $cekEncrypted = base64_decode($content["x-kss-key"]);
             $encryptionInfo["cek"] = $cek = EncryptionUtil::decodeCek($this->encryptionMaterials, $cekEncrypted);
         } else {
             $encrypted = FALSE;
         }
     }
     //是否为下载到文件中
     $isWriteToFile = FALSE;
     if ($encrypted) {
         $iv = $encryptionInfo["iv"];
         $cek = $encryptionInfo["cek"];
         if (empty($iv)) {
             throw new Ks3ClientException("can not find iv in UserMeta or InstructionFile");
         }
         if (empty($cek)) {
             throw new Ks3ClientException("can not find cek in UserMeta or InstructionFile");
         }
         if (isset($args["Range"])) {
             $range = $args["Range"];
             if (!is_array($range)) {
                 if (preg_match('/^bytes=[0-9]*-[0-9]*$/', $range)) {
                     $ranges = explode("-", substr($range, strlen("bytes=")));
                     $a = $ranges[0];
                     $b = $ranges[1];
                     if ($a > $b) {
                         throw new Ks3ClientException("Invalid range " . $range);
                     }
                     $range = array("start" => $a, "end" => $b);
                 } else {
                     throw new Ks3ClientException("Invalid range " . $range);
                 }
             } else {
                 if (!isset($range["start"]) || !isset($range["end"])) {
                     throw new Ks3ClientException("Invalid range " . serialize($range));
                 }
                 if ($range["start"] > $range["end"]) {
                     throw new Ks3ClientException("Invalid range " . serialize($range));
                 }
             }
         }
         $isWriteToFile = isset($args["WriteTo"]);
         $contentLength = $meta["ObjectMeta"]["Content-Length"];
         if ($isWriteToFile) {
             $writeCallBack = new AESCBCStreamWriteCallBack();
             $writeCallBack->iv = $iv;
             $writeCallBack->cek = $cek;
             $writeCallBack->contentLength = $contentLength;
             if (isset($range)) {
                 $blocksize = mcrypt_get_block_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC);
                 $adjustedRange = EncryptionUtil::getAdjustedRange($range, $blocksize);
                 $writeCallBack->expectedRange = $range;
                 $writeCallBack->adjustedRange = $adjustedRange;
                 $args["Range"] = $adjustedRange;
             }
             $args["writeCallBack"] = $writeCallBack;
             return $this->ks3client->getObject($args);
         } else {
             $offset = 0;
             $blocksize = mcrypt_get_block_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC);
             if (isset($range)) {
                 $adjustedRange = EncryptionUtil::getAdjustedRange($range, $blocksize);
                 $args["Range"] = $adjustedRange;
             }
             $s3Object = $this->ks3client->getObject($args);
             $content = $s3Object["Content"];
             if (isset($range)) {
                 if ($adjustedRange["start"] > 0) {
                     $iv = substr($content, 0, $blocksize);
                     $content = substr($content, $blocksize);
                     $offset = $blocksize + $adjustedRange["start"];
                 }
             }
             if (!empty($content)) {
                 $td = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', MCRYPT_MODE_CBC, '');
                 mcrypt_generic_init($td, $cek, $iv);
                 $decoded = mdecrypt_generic($td, $content);
                 mcrypt_generic_deinit($td);
                 mcrypt_module_close($td);
             } else {
                 $decoded = "";
             }
             //判断是否需要删除最后填充的字符,以及获取填充的字符
             $needRemovePad = FALSE;
             $pad = NULL;
             if ($offset + strlen($decoded) >= $contentLength) {
                 $needRemovePad = TRUE;
                 $pad = ord(substr($decoded, strlen($decoded) - 1, 1));
                 if ($pad <= 0 || $pad > $blocksize) {
                     //invalid pad
                     $needRemovePad = FALSE;
                 }
             }
             $endOffset = 0;
             if (isset($range)) {
                 if ($offset + strlen($decoded) > $range["end"]) {
                     $preLength = strlen($decoded);
                     $decoded = substr($decoded, 0, $range["end"] - $offset + 1);
                     $endOffset = $preLength - strlen($decoded);
                 }
                 if ($offset < $range["start"]) {
                     $decoded = substr($decoded, $range["start"] - $offset);
                 }
             }
             //再次根据截取的长度判断是否需要删除最后填充的字符
             if ($needRemovePad && $endOffset > $pad) {
                 $needRemovePad = FALSE;
             }
             if ($needRemovePad) {
                 $padOffset = $pad - $endOffset;
                 $actualWriteCount = strlen($decoded) - $padOffset;
                 if ($actualWriteCount <= 0) {
                     //负数的情况就是用户期望的range里全是填充的
                     $decoded = "";
                 } else {
                     $decoded = substr($decoded, 0, strlen($decoded) - $padOffset);
                 }
             }
             $s3Object["Content"] = $decoded;
             return $s3Object;
         }
     } else {
         return $this->ks3client->getObject($args);
     }
 }