Home > database >  AWS S3 generate presigned URL in Visual Basic
AWS S3 generate presigned URL in Visual Basic

Time:11-15

we have to calculate a presigned URL to access S3 and con not use external libs (like Chilkat) or the AWS SDK for .NET with Visual Basic. Hence, we have to do the signature calculation on my own.

Some things I already validated:

  • I validated the functions "get_HASH_SHA256", "ConvToHexString" and "HmacSHA256" are working as expected with external 3rd party tools.
  • I calculated the presigned URL with Postman and compared the required query parameters with mine. Everything seems to be fine here. When I use the signature from postman, the request works as expected.

My code:

' src: https://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-query-string-auth.html
  CanonicalRequest = "GET" & vbLf
  CanonicalRequest = CanonicalRequest & "/reports/XXXXXXX" & vbLf
  CanonicalRequest = CanonicalRequest & "X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=MYACCESSKEY/20221109/eu-west-1/s3/aws4_request&X-Amz-Date=20221109T075928Z&X-Amz-Expires=86400&X-Amz-SignedHeaders=host" & vbLf
  CanonicalRequest = CanonicalRequest & "host:mybucket.s3.eu-west-1.amazonaws.com" & vbLf & vbLf
  CanonicalRequest = CanonicalRequest & "host" & vbLf & "UNSIGNED-PAYLOAD"
  
  Debug.Print "CanonicalRequest:"
  Debug.Print CanonicalRequest
  
  stringToSign = "AWS4-HMAC-SHA256" & vbLf
  stringToSign = stringToSign & "20221109T075928Z" & vbLf
  stringToSign = stringToSign & "20221109/eu-west-1/s3/aws4_request" & vbLf
  stringToSign = stringToSign & get_HASH_SHA256(CanonicalRequest)
  
  Debug.Print "StringToSign:"
  Debug.Print stringToSign
   
  
  SigningKey = HmacSHA256(HmacSHA256(HmacSHA256(HmacSHA256("AWS4" & SecretKey, "20221109"), "eu-west-1"), "s3"), "aws4_request")
  
  Debug.Print "SigningKey:"
  Debug.Print SigningKey
  
  ' Signature = (HmacSHA256(SigningKey, stringToSign)) tried w/o hex conversion
  Signature = ConvToHexString(HmacSHA256(SigningKey, stringToSign))
  ' Result should be ****003a740
  ' Result is ***6e9502

Any VB expert here, who can confirm the stringToSign and CanonicalRequest are calculated correctly?

CodePudding user response:

It's working now. The calculated signing key was wrong.

How did I resolve this?

What helped me resolving this was the section "Deriving a signing key using other languages" of this aws help page. Here they provided actual samples. I used the secret and access key provided there and compared the results with the expected results. The first hash value (in the sample kDate) was correct, but the second hash was a different one (in the sample kRegion).

The issue with my code above was, that i converted the signature to hex, before I calculated the next hash.

But as written on the help page: Note that these are hex-encoded representations of the binary data; the key itself and the intermediate values should be in binary format.

So I changed the logic to use the binary results:

Public Function getSigningKey(ByVal key As String, dateStamp As String, regionName As String, serviceName As String) As String
 Dim asc As Object
 Set asc = CreateObject("System.Text.UTF8Encoding")
 
 Dim keyAsByte() As Byte
 Dim kdate() As Byte
 Dim kregion() As Byte
 Dim kservice() As Byte
 Dim ksigning() As Byte
 
 keyAsByte = asc.GetBytes_4(key)
 kdate = HmacSHA256(keyAsByte, dateStamp)
 kregion = HmacSHA256(kdate, regionName)
 kservice = HmacSHA256(kregion, serviceName)
 
 getSigningKey = HmacSHA256(kservice, "aws4_request")
 
End Function

Public Function HmacSHA256(ByRef sSharedSecretKey() As Byte, ByVal sTextToHash As String) As String

    Dim asc As Object, enc As Object
    Dim TextToHash() As Byte
    Dim SharedSecretKey() As Byte
    Set asc = CreateObject("System.Text.UTF8Encoding")
    Set enc = CreateObject("System.Security.Cryptography.HMACSHA256")

    TextToHash = asc.GetBytes_4(sTextToHash)
    enc.key = sSharedSecretKey

    Dim bytes() As Byte
    HmacSHA256 = enc.ComputeHash_2((TextToHash))
    
    
    Set asc = Nothing
    Set enc = Nothing

End Function
  • Related