POST (AWS 署名バージョン 4) を使用したブラウザベースのアップロードについて

- このドキュメントは、実際に動いたものを例示することを目的として書かれています。

### policy と x-amz-signature の算出方法など全部(node 12)

```JavaScript
const cryp = require("crypto");

const credkey = "アクセスキー"
const secret = "シークレット"
const bucketName = "バケット名"

const regionName = "ap-northeast-1"
const serviceName = "s3"
const expiration = "2020-06-11T12:00:00.000Z"
const operation = "aws4_request"

function sha256(state,input){
    return cryp.createHmac("sha256", state).update(input).digest() 
}

function sha256hex(state,input){
    return cryp.createHmac("sha256", state).update(input).digest('hex') 
}

exports.handler = async (event) => {
    
    const fullDateTime = (new Date()).toISOString().replace(/[-:]/g,"").replace(/\.[0-9]*/g,"")
    const dateStamp = fullDateTime.replace(/T.*/g,"")
 
    const policy = {
         "expiration": expiration,
         "conditions": [
             { "bucket": bucketName },
             ["starts-with", "$key", ""],
             { "acl": "private" },
             { "x-amz-server-side-encryption": "AES256" },
             { "x-amz-credential": credkey + "/" + dateStamp + "/" + regionName + "/" + serviceName + "/" + operation },
             { "x-amz-algorithm": "AWS4-HMAC-SHA256" },
             { "x-amz-date":  fullDateTime}
         ]
     };
 
 
     var stringify = JSON.stringify(policy);

 
    const sigver = "AWS4"
 
    const dateKey =  sha256(sigver + secret,dateStamp) 
    const dateRegionKey = sha256(dateKey,regionName)
    const dateRegionServiceKey = sha256(dateRegionKey,serviceName)
    const signingKey = sha256(dateRegionServiceKey,operation)
    
    var policy64 = new Buffer.from(stringify).toString('base64') // これが policy
    var signature = sha256hex(signingKey,policy64) // これが x-amz-signature
    
 const HERE =`
     <html><head>
     <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
     </head><body>
     <form method="post" action="https://${bucketName}.s3.${regionName}.amazonaws.com/" enctype="multipart/form-data">
     
     <p>
     key <input type="text" name="key" value="uploadedObject" /><br/>
     acl <input type="text" name="acl" value="private" /><br/>
      xsse <input type="text" name="x-amz-server-side-encryption" value="AES256" /> <br/>
     buc <input type="text" name="bucket" value="${bucketName}" /><br/>
     poli <input type="text" name="policy" value="${policy64}" /><br/>
     xal <input type="text" name="x-amz-algorithm" value="AWS4-HMAC-SHA256" /><br/>
     xcre <input type="text" name="x-amz-credential" value="${credkey}/${dateStamp}/${regionName}/${serviceName}/${operation}" /><br/>
     xdate <input type="text" name="x-amz-date" value="${fullDateTime}" /><br/>
     xsig <input type="text" name="x-amz-signature" value="${signature}" /><br/>
     
     フォーム構成要素の一番最後に input.file を書くこと
     
     <input type="file" name="file"></p>
     
     <p><input type="submit" value="送信する"></p>
     
     </form>
     </body>
     </html>
`
     const response = {
         statusCode: 200,
         body: JSON.stringify(
             //['Hello from Lambda!', policy64 + "/" +  signature ]
              HERE 
             ),
     };
     
     return response;
 };

exports.handler().then(p=>{
   console.log( JSON.parse(p.body)) 
})


```

実際にPOSTに使えるHTMLは、JavaScriptの出力を見てください。こんな感じのが出ます。

```HTML
     <html><head>
     <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
     </head><body>
     <form method="post" action="https://example.s3.ap-northeast-1.amazonaws.com/" enctype="multipart/form-data">
     
     <p>
     key <input type="text" name="key" value="uploadedObject" /><br/>
     acl <input type="text" name="acl" value="private" /><br/>
      xsse <input type="text" name="x-amz-server-side-encryption" value="AES256" /> <br/>
     buc <input type="text" name="bucket" value="example" /><br/>
     poli <input type="text" name="policy" value="example" /><br/>
     xal <input type="text" name="x-amz-algorithm" value="AWS4-HMAC-SHA256" /><br/>
     xcre <input type="text" name="x-amz-credential" value="example/20190611/ap-northeast-1/s3/aws4_request" /><br/>
     xdate <input type="text" name="x-amz-date" value="example" /><br/>
     xsig <input type="text" name="x-amz-signature" value="example" /><br/>
     
     フォーム構成要素の一番最後に input.file を書くこと
     
     <input type="file" name="file"></p>
     
     <p><input type="submit" value="送信する"></p>
     
     </form>
     </body>
     </html>
```

大体こんな感じ。