Classic ASP amazon s3 rest authorisation

前端 未结 3 2158
夕颜
夕颜 2021-02-07 20:33

I am confused on what I am doing wrong here...



        
3条回答
  •  时光说笑
    2021-02-07 21:08

    The Amazon Signature must be url encoded in a slightly different way to what VBSCript encodes. The following function will encode the result correctly:

    JScript Version:

    function amazonEncode(s)
    {
        return Server.UrlEncode(s).replace(/\+/g,"%20").replace(/\%2E/g,".").replace(/\%2D/g,"-").replace(/\%7E/g,"~").replace(/\%5F/g,"_");
    }
    

    VBScript Version:

    function amazonEncode(s)
        dim retval
        retval = Server.UrlEncode(s)
        retval = replace(retval,"+","%20")
        retval = replace(retval,"%2E",".")
        retval = replace(retval,"%2D","-")
        retval = replace(retval,"%7E","~")
        retval = replace(retval,"%5F","_")
        amazonEncode = retval
    end function
    

    As for base64, I used .NET's already built functionality for it. I had to create a DLL to wrap it, so that I could use it from JScript (or VBScript).

    Here's how to create that dll:

    Download the free C# 2010 Express and install it.
    You also need to use two other tools that you won’t have a path to, so you will need to add the path to your PATH environment variable, so at a cmd prompt search for regasm.exe, guidgen.exe and sn.exe (you might find several versions – select the one with the latest date).
    •   cd\
    •   dir/s regasm.exe
    •   dir/s sn.exe
    •   dir/s guidgen.exe
    
    
    So as an example, a COM object that has just one method which just returns “Hello”:
    Our eventual aim is to use it like this:
    <%@Language=JScript%>
    <%
    var x = Server.CreateObject("blah.whatever");
    Response.Write(x.someMethod());
    %>
    
    or 
    
    <%@Language=VBScript%>
    <%
    dim x
    set x = Server.CreateObject("blah.whatever")
    Response.Write x.someMethod()
    %>
    
    •   Start C# and create a new project
    •   Select “Empty Project”
    •   Give it a name – this becomes the namespace by default (the blah in the sample above)
    •   Next save the project (so you know where to go for the next bit).  This will create a folder structure like so:
    o   blah    this contains your solution files that the editor needs (blah.sln etc)
       blah    this contains your source code and project files
    •   bin
    o   Debug           the compiled output ends up here
    •   Next, using the cmd console, navigate to the root blah folder and create a key pair file:
       sn –k key.snk
    •   Next you need a unique guid (enter guidgen at the cmd prompt)
    o   Select registry format
    o   Click “New Guid”
    o   Click “Copy”
    •   Back to C# editor – from the menu, select Project – Add Class
    •   Give it a name – this is the whatever in the sample above
    •   After the opening brace just after the namespace line type:
       [GuidAttribute(“paste your guid here”)]
       remove the curly brackets from your pasted guid
    •   You will need to add another “using” at the top
      using System.Runtime.InteropServices;
    •   Finally you need to create someMethod
    
    The final C# code looks like this (the bits in red may be different in your version):
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Runtime.InteropServices;
    
    namespace blah
    {
        [GuidAttribute("AEF4F27F-9E97-4189-9AD5-64386A1699A7")]
        public class whatever
        {
            public string someMethod()
            {
                return "Hello";
            }
        }
    }
    
    •   Next, from the menu, select Project – Properties
    o   On the left, select Application and, for the Output type dropdown, select “Class Library”
    o   On the left, select Signing and tick the “Sign the assembly” box, then browse to the key.snk file you made earlier
    o   Save the properties (CTRL-S)
    •   Next build the dll (Press F6) – This will create a dll in the Debug folder
    •   Open a cmd window as administrator (right click cmd.exe and select “Run as Administrator”)
    •   Navigate to the Debug folder and enter the following to register the assembly:
      regasm blah.dll /tlb:blah.tlb /codebase blah
    
    That’s it – the above is a genuine COM component and will work in other applications, the example below allows for event handling and only really works in ASP due to the default property mechanism of ASP:
    

    The code for the base64 stuff would be:

        // returns a base 64 encoded string that has been encrypted with SHA256
        // parameters:
        //  s   string to encrypt
        //  k   key to use during encryption
        public string getBase64SHA256(string s, string k)
        {
            HMACSHA256 sha = new HMACSHA256();
            System.Text.UTF8Encoding encoding = new System.Text.UTF8Encoding();
            sha.Key = encoding.GetBytes(k);
            byte[] hashBytes = sha.ComputeHash(encoding.GetBytes(s));
            return System.Convert.ToBase64String(hashBytes);
        }
    
        // returns a base 64 encoded string that has been encrypted with SHA1
        // parameters:
        //  s   string to encrypt
        //  k   key to use during encryption
        public string getBase64SHA1(string s, string k)
        {
            HMACSHA1 sha = new HMACSHA1();
            System.Text.UTF8Encoding encoding = new System.Text.UTF8Encoding();
            sha.Key = encoding.GetBytes(k);
            byte[] hashBytes = sha.ComputeHash(encoding.GetBytes(s));
            return System.Convert.ToBase64String(hashBytes);
        }
    

    You would need the relevant usings:

    using System.Security.Cryptography;
    

    The signature in full must have all the query string name-value pairs in alphabetical order before computing the SHA and base64. Here is my version of the signature creator function:

    function buildAmazonSignature(host,req,qstring)
    {
        var str="", i, arr = String(qstring).split("&");
    
        for (i=0; ib[0])?1:0);
    }
    

    VBScript doesn't have a very good array sort facility, so you'll have to work that one out yourself - sorry

    Also I have the timestamp in this format:

    YYYY-MM-DDTHH:MM:SSZ

    Also the stuff in the query string included the following:

    AWSAccessKeyId
    SignatureMethod
    SignatureVersion
    Version
    Expires
    Action
    

    Hope that helps

提交回复
热议问题