Home » Posts tagged "base64"

Command Line 下把 Hex 轉成 Base64...

每次都忘記,寫一篇之後查比較方便... 重點在對 xxd 的變化應用,而 xxd 被包在 Vim 裡,所以應該都會裝... 吧...

xxd 預設是把 binary 轉成 hex,但你可以用 -r 參數變成反向,也就是 hex 轉 binary。

所以剩下的就很簡單了,先把 hex 轉成 binary 再轉成 base64:

echo 0123456789ABCDEF | xxd -r -p | base64

這邊有裝 Base64 所以可以直接用,如果沒有的話,可以用 OpenSSL 替代:

echo 0123456789ABCDEF | xxd -r -p | openssl enc -base64

Amazon CloudFront 上 Protected Content 的 URL Sign...

Amazon CloudFront 也可以設定要簽名才能抓檔案,只是 URL Sign 設計的觀念跟 Amazon S3 完全不一樣,這不一致的調調很... 詭異...

大致上有這些差異:

  • Amazon S3 用的是 HMAC-SHA1 的機制簽名 (shared secret,也就是 Amazon S3 與你都有同一把 key),而 Amazon CloudFront 則是用 RSA key 簽名 (public key,也就是 Amazon CloudFront 存放 public key,你自己存放 private key)。
  • 也因為是使用 RSA key,有人會誤解跟 Amazon EC2 用的 RSA key 相同。但實際上需要在 Security Credentials 頁裡設,有專門對 Amazon CloudFront 用的 RSA key 的段落。
  • 自己對 Base64 編碼再處理,避開使用 += 以及 /。但不是有標準可以用嗎,為什麼要自己發明呢...
  • 引入 Policy 的彈性機制,不僅可以對時間控制,也可以對 IP address 控制,但 Policy 這是帶在 URL 裡傳進去的... 你可以看到我的程式碼內產生出 $json_str 後簽完名帶到 URL 內了。

官方的 CloudFront Signed URLs in PHP 這篇的範例程式碼其實很清楚了,要直接拿去用其實也沒麼問題。我自己整理後是這樣:

<?php

$key_pair_id = 'APKA...';
$pem_file = '';
$resource = 'http://test2-cdn.gslin.org/test.txt';

$expires = time() + 3600;

$json_str = json_encode(
    array(
        'Statement' => array(
            array(
                'Resource' => $resource,
                'Condition' => array(
                    'DateLessThan' => array(
                        'AWS:EpochTime' => $expires
                    )
                )
            )
        )
    ),
    JSON_UNESCAPED_SLASHES
);

$buf = file_get_contents($pem_file);
$key = openssl_get_privatekey($buf);

openssl_sign($json_str, $signed_policy, $key, OPENSSL_ALGO_SHA1);

openssl_free_key($key);

$signature = str_replace(
    array('+', '=', '/'),
    array('-', '_', '~'),
    base64_encode($signed_policy)
);

echo "${resource}?",
    "Expires=${expires}&",
    "Signature=${signature}&",
    "Key-Pair-Id=${key_pair_id}\n";

反正你搞不太懂 Amazon 為什麼要這樣設計的... =_=

Archives