[VB6] HMAC-SHA-256, HMAC-SHA-1 Using Crypto API-VBForums
Results 1 to 40 of 40

Thread: [VB6] HMAC-SHA-256, HMAC-SHA-1 Using Crypto API

  1. #1

    Thread Starter
    PowerPoster
    Join Date
    Feb 2006
    Posts
    11,009

    [VB6] HMAC-SHA-256, HMAC-SHA-1 Using Crypto API

    Title

    HS256, a class for calculating HMAC-SHA-256 from a Key and Data in VB6.

    note:

    HS1 (HMAC-SHA-1) also included now. Scroll down to the latest versions of both!

    Description

    The HS256 class uses Windows Crypto API calls wherever possible to calculate HMACs (Hash-based Message Authentication Codes) based on SHA 256 hashes. The class also provides formatting functions between binary data and Strings (Base64, Hex, and Hex variations) as well as converting Strings to and from UTF8 encoding.

    All of these things are useful in creating message authentication strings for many purposes. These HMACs are needed in message authentication for the SOAP and REST APIs provided by many cloud computing services. They are also sometimes used to sign other types of messages (e.g. email).

    Feature list
    • HMAC-SHA-256 calculation without the use of any external cryptography components, relies on the Windows Crypto API.
    • Translation of binary data to and from Base64 strings.
    • Translation of binary data to and from Hex strings (several variations such as Hex with address and ASCII).
    • Translation of standard "Unicode" (UTF16-LE) String data to and from UTF8 encoding.

    Screenshot

    Screenshot of the (attached) demo shown below.

    Author name

    Bob Riemersma

    System requirements

    Requires Windows XP or later. May require XP SP1 or SP2 (Crypto API documentation is not explicit on this point). Some minor format variations are emulated under Windows XP instead being performed via Crypto API calls, one minor sub-variation is only available in Windows 2003 R2, Vista, or later.

    No special processor, disk, or memory requirements. Requires Visual Basic 6.0 development system, preferably Service Pack 6b or later, Standard Edition or better.

    License info

    This software is released into the Public Domain. It may be used for any purpose as is or in derivative works. No warranty of fitness or merchantability, and no support is offered. This source code is available AS IS.

    Usage

    Add the class module to your VB6 project. See comments at the head of the source regarding use of the methods and properties provided.

    The demonstration project

    The HS256 class is posted here as part of a demo program.

    This program demonstrates the 7 SHA-256 Test Case vector sets found in RFC 4231:

    Identifiers and Test Vectors for HMAC-SHA-224, HMAC-SHA-256,
    HMAC-SHA-384, and HMAC-SHA-512
    Attached Images Attached Images  
    Attached Files Attached Files
    Last edited by dilettante; Apr 16th, 2011 at 09:00 PM.

  2. #2

    Thread Starter
    PowerPoster
    Join Date
    Feb 2006
    Posts
    11,009

    Re: [VB6] HMAC-SHA-256 Using Crypto API

    Update.

    Version 2.0 of the HS256 class:
    • Cleanup of extraneous comments.
    • Revised object model allows more efficient calculation of multiple HMACs using the same key.
    • Added MD5 hash function, often needed in programs using HMACs.
    Attached Files Attached Files

  3. #3

    Thread Starter
    PowerPoster
    Join Date
    Feb 2006
    Posts
    11,009

    Re: [VB6] HMAC-SHA-256 Using Crypto API

    WSTime

    This is a pair of classes meant to be used as an adjunct to the HMAC-SHA-256 class when working with Web Services, primarily REST APIs like those of Azure or AWS.

    Caveats, license terms, etc. are the same as spelled out for HS256 above.


    These classes are identical in their methods, and format VB6 Date values to/from HTTP (RFC 1123) and ISO 8601 timestamp strings with time zone conversion.

    WinHttpTime uses entrypoints in winhttp.dll

    WinInetTime uses entrypoints in wininet.dll

    A normal program would never use both classes. The idea was to avoid having to load both DLLs (oleaut32.dll and wininet.dll) for a program using WinHttpRequest. However I believe the VB6 runtime always loads wininet.dll and probably both for the process anyway, which probably makes WinHttpTime entirely redundant (i.e. always use WinInetTime).

    The classes are declared so that they produce a default instance (PredeclaredId = True). Programs using these classes don't have to create an instance, there will be a global instance named the same as the class.

    This is not true of the HS256 class, since you might well need several instances, all initialized to different keys.


    The attachment is a trivial demo containing and showing the operation of both classes.

    Note: To clarify, these two classes are two ways of doing the same things.
    Attached Files Attached Files
    Last edited by dilettante; Apr 14th, 2012 at 01:43 PM. Reason: added note

  4. #4

    Thread Starter
    PowerPoster
    Join Date
    Feb 2006
    Posts
    11,009

    Re: [VB6] HMAC-SHA-256 Using Crypto API

    Another update: Version 2.1

    Minor cleanup.


    Also... due to popular demand an HMAC-SHA-1 implementation created from the most recent HMAC-SHA-256 edition.

    The demo incorporates test vectors from RFC 2202:

    Test Cases for HMAC-MD5 and HMAC-SHA-1

    Please verify these further if you have other known test cases. We'd like to have these cleaned up so people can rely on them. Looking good so far though!


    These two Classes are separate since a program normally would only need one or the other, which is also why many auxiliary functions are duplicated between them.
    Attached Files Attached Files
    Last edited by dilettante; Apr 16th, 2011 at 09:02 PM.

  5. #5
    New Member
    Join Date
    May 2011
    Posts
    2

    Re: [VB6] HMAC-SHA-256 Using Crypto API

    This HMAC SHA256 implementation has helped me greatly. Thanks!

  6. #6

    Thread Starter
    PowerPoster
    Join Date
    Feb 2006
    Posts
    11,009

    Re: [VB6] HMAC-SHA-256, HMAC-SHA-1 Using Crypto API

    Great! Glad somebody else got some use out of it.

  7. #7
    New Member
    Join Date
    Sep 2011
    Posts
    8

    Re: [VB6] HMAC-SHA-256, HMAC-SHA-1 Using Crypto API

    I just read this post and I'm hoping you can help me out. I am a VB6 programmer, but until recently I knew nothing about XML and currently still know nothing about HMAC SHA-256 encryption.

    The company I'm working for needs to me to develop an Amazon app to download our order information and Amazon requires a "Signature" parameter to be inserted in their XML queries. This needs to be (forgive me if I state this awkwardly as I barely know what I'm talking about) the result of some parameters encrypted using HMAC SHA-256 and then converted to HMAC Base 64.

    From the looks of your sample program, I can see that this may be able to give me the information I need. I've downloaded it and I can run it and see the results, but really what I need is a simple VB6 function to convert a key and data string to SHA-256 and perhaps I just haven't had enough sleep, but I can't figure out where that is in your program.

    Could you give a tired, slightly dim programmer a nudge in the right direction? Thanks!

  8. #8

    Thread Starter
    PowerPoster
    Join Date
    Feb 2006
    Posts
    11,009

    Re: [VB6] HMAC-SHA-256, HMAC-SHA-1 Using Crypto API

    I hope this helps.

    Going through the AWS SimpleDB documentation for REST Authentication I find the docs are good but not great. They leave out small tidbits and swing between specific and vague on important things like character encoding, what precisely they mean by "newline" and other small things. HS256 itself took some work, but figuring out the AWS "canonicalization" process is a small nightmare. They outline the steps but leaving you hanging here and there on specifics.

    They even give an example but don't show what the final Signature should be, making verification of my example here difficult.

    In any case, the example attached here is way stripped down but with copious comments. In those comments I have made notes about a few points you may need to get clarification on. Try the AWS developer support forums for answers.


    Keep in mind that different Amazon Services have different requirements. Grab all of the docs they offer (old and new) for the Service you need to use.
    Attached Images Attached Images  
    Attached Files Attached Files
    Last edited by dilettante; Sep 8th, 2011 at 10:05 PM. Reason: reposted attachment - typos in code comments, doh!

  9. #9
    New Member
    Join Date
    Sep 2011
    Posts
    8

    Re: [VB6] HMAC-SHA-256, HMAC-SHA-1 Using Crypto API

    That is awesome! Thank you! I'm still not quite there because I can't figure out what string Amazon wants to add to the key (which is presumably my AWS Access Key ID) to arrive at the signature string.

    They've provided me with a link to tool called the MWS Scratchpad, and from there, I can see that the signature changes all the time, so I think the timestamp must be included in the string to process somehow? I've sent them a support email request and it's been a couple of days and they haven't answered - they are pretty slow with this generally.

    https://mws.amazonservices.com/scratchpad/index.html

    Thanks again, this helps me out immensely!

  10. #10

    Thread Starter
    PowerPoster
    Join Date
    Feb 2006
    Posts
    11,009

    Re: [VB6] HMAC-SHA-256, HMAC-SHA-1 Using Crypto API

    Yes, a fresh Timestamp is probably one of the headers you need for the Marketplace Web Service (or whatever it is) much like the generalized AWS offerings. That and your Access Key ID header go into building the "string to sign." I'm sure their different services each have their own requirements for additional headers.

    Some services may not use the "headers" of the "string to sign" as actual request headers, but instead send them as a parameter string (part of the URL). They may want a User-Agent header though (that does not seem to be part of the signature).

    Perhaps the Scratchpad will help you get it all unraveled.

    Good luck!

  11. #11
    New Member
    Join Date
    Sep 2011
    Posts
    8

    Re: [VB6] HMAC-SHA-256, HMAC-SHA-1 Using Crypto API

    So, just in case I can't get any useful information out of Amazon, is there some way I can decode the signature that their MWS Scratchpad app gives me - it was created with (I think) my AWS Access Key ID and some mystery string. The Scratchpad gives me a value for "SHA 256 HMAC" (some big long incoherent string) and "Base64 HMAC" which is the value used for the Signature parameter.

    Is there some way to take my AWS Access Key ID and one of the values they give me to decode the original string so I can look at it in text format? If I had that, I think I might be able to finish my app pretty quickly.

  12. #12

    Thread Starter
    PowerPoster
    Join Date
    Feb 2006
    Posts
    11,009

    Re: [VB6] HMAC-SHA-256, HMAC-SHA-1 Using Crypto API

    No, it doesn't go backwards. These are one-way hash operations which is sort of the point. At Amazon's end they validate by taking your ID you sent, looking up the "secret key" in their database, and parts from the request contents and then doing the same calculation as you. Then they compare the signature they get with the one you sent.

    So everything is critical from character encoding to order of operations, what gets included in the "string to sign" and what gets left out. It almost feels like 90% of the security of this process is how confusing it is to duplicate even based on their documentation. The "good news" is Azure and other services are just as bad about this.

    I looked at MWS Scratchpad and the main benefit it might offer you is a way to validate your results without actually having to "hit" the service. You could compare the signature output by your code against the signature created by Scratchpad and tweak your code until you get the same thing.


    The details for MWS are described starting at Page 11 of this document:

    https://images-na.ssl-images-amazon....159025605_.pdf

    You might even want to print out the pages about this topic and get out three colors of pens and 5 colors of highlighting markers and go at it studying hard.
    Last edited by dilettante; Sep 10th, 2011 at 08:12 AM.

  13. #13
    Junior Member
    Join Date
    Mar 2006
    Posts
    19

    Re: [VB6] HMAC-SHA-256, HMAC-SHA-1 Using Crypto API

    My primary use of this class is in an Access db with vba. Your class works for me through most of my environments, however..

    I have two windows 7 machines and an xp machine. On one of the windows 7 machines the class fails during initialization on this line as a class within the Access db:
    Vb Code:
    1. ElseIf CryptAcquireContext(hAdvProvider, _
    2.                                0&, _
    3.                                StrPtr(strProvider), _
    4.                                PROV_RSA_AES, _
    5.                                CRYPT_VERIFYCONTEXT) = 0 Then
    6.         Err.Raise vbObjectError Or &HC368&, _
    7.                   "HS256.Class_Initialize", _
    8.                   "Failed to obtain CryptoAPI RSA AES context, system error " _
    9.                 & CStr(Err.LastDllError)
    10.     End If
    However, your vb6 demo works fine on the same machine.

    The class also works within the Access db on the other windows 7 machine and on the xp machine.

    So it seems it can create a base provider but not an advanced provider (from within the Access Db):

    Vb Code:
    1. If CryptAcquireContext(hBaseProvider, _
    2.                            0&, _
    3.                            StrPtr(MS_DEFAULT_PROVIDER), _
    4.                            PROV_RSA_FULL, _
    5.                            CRYPT_VERIFYCONTEXT) = 0 Then
    6.         Err.Raise vbObjectError Or &HC366&, _
    7.                   "HS256.Class_Initialize", _
    8.                   "Failed to obtain CryptoAPI Base context, system error " _
    9.                 & CStr(Err.LastDllError)
    10.     ElseIf CryptAcquireContext(hAdvProvider, _
    11.                                0&, _
    12.                                StrPtr(strProvider), _
    13.                                PROV_RSA_AES, _
    14.                                CRYPT_VERIFYCONTEXT) = 0 Then
    15.         Err.Raise vbObjectError Or &HC368&, _
    16.                   "HS256.Class_Initialize", _
    17.                   "Failed to obtain CryptoAPI RSA AES context, system error " _
    18.                 & CStr(Err.LastDllError)
    19.     End If
    Any guesses as to what the cause of this would be? Maybe a missing win7 service pack?

    Thanks - and much appreciated!

  14. #14

    Thread Starter
    PowerPoster
    Join Date
    Feb 2006
    Posts
    11,009

    Re: [VB6] HMAC-SHA-256, HMAC-SHA-1 Using Crypto API

    What is unusual about the Windows 7 machine with the problem?

    Do you have 64-bit Access installed on it?

  15. #15
    Junior Member
    Join Date
    Mar 2006
    Posts
    19

    Re: [VB6] HMAC-SHA-256, HMAC-SHA-1 Using Crypto API

    Good question. It's Access 2007 though, just like on the XP system. And actually on the other Win 7 machine I'm using Access 2010 and it works


    system error -2146893799

    So:
    Win 7 Access 2010 -- works
    Win 7 Access 2007 -- broken
    XP Access 2007 -- works

    And your demo I know works on both Win 7 systems.

    Thanks...

    Maybe it has to do with Administrator settings? I think a while ago I adjusted the (working) Win 7 to accept me as admin default.

  16. #16

    Thread Starter
    PowerPoster
    Join Date
    Feb 2006
    Posts
    11,009

    Re: [VB6] HMAC-SHA-256, HMAC-SHA-1 Using Crypto API

    Well I still wonder if Access 2007 64-bit might be involved.

    Was there an error number (Err.LastDLLError)?

  17. #17
    Junior Member
    Join Date
    Mar 2006
    Posts
    19

    Re: [VB6] HMAC-SHA-256, HMAC-SHA-1 Using Crypto API

    Yes, the error number was -2146893799

    So the only difference is that this is Access 2007 (x86) on Win 7 (x64).

    This is not the 64bit version of Access.

  18. #18

    Thread Starter
    PowerPoster
    Join Date
    Feb 2006
    Posts
    11,009

    Re: [VB6] HMAC-SHA-256, HMAC-SHA-1 Using Crypto API

    Well this error is NTE_KEYSET_NOT_DEF (&H80090019) "The requested provider does not exist."

    Very strange.

    Are you somehow using Access in a non-interactive session?

    Something to try, adding a flag bit. Make these changes:

    Near the top
    Code:
    Private Const PROV_RSA_FULL              As Long = 1
    Private Const PROV_RSA_AES               As Long = 24
    Private Const CRYPT_VERIFYCONTEXT        As Long = &HF0000000
    Private Const CRYPT_MACHINE_KEYSET       As Long = 32  <-- new Const
    Private Const MS_DEFAULT_PROVIDER        As String = _
        "Microsoft Base Cryptographic Provider v1.0"
    Private Const MS_ENH_RSA_AES_PROV        As String = _
        "Microsoft Enhanced RSA and AES Cryptographic Provider"
    Private Const MS_ENH_RSA_AES_PROV_XP     As String = _
        "Microsoft Enhanced RSA and AES Cryptographic Provider (Prototype)"
    Inside Class_Initialize
    Code:
        If CryptAcquireContext(hBaseProvider, _
                               0&, _
                               StrPtr(MS_DEFAULT_PROVIDER), _
                               PROV_RSA_FULL, _
                               CRYPT_VERIFYCONTEXT Or CRYPT_MACHINE_KEYSET) = 0 Then  <-- add flag
            Err.Raise vbObjectError Or &HC366&, _
                      "HS256.Class_Initialize", _
                      "Failed to obtain CryptoAPI Base context, system error " _
                    & CStr(Err.LastDllError)
        ElseIf CryptAcquireContext(hAdvProvider, _
                                   0&, _
                                   StrPtr(strProvider), _
                                   PROV_RSA_AES, _
                                   CRYPT_VERIFYCONTEXT Or CRYPT_MACHINE_KEYSET) = 0 Then  <-- add flag
            Err.Raise vbObjectError Or &HC368&, _
                      "HS256.Class_Initialize", _
                      "Failed to obtain CryptoAPI RSA AES context, system error " _
                    & CStr(Err.LastDllError)
        End If

  19. #19
    Junior Member
    Join Date
    Mar 2006
    Posts
    19

    Re: [VB6] HMAC-SHA-256, HMAC-SHA-1 Using Crypto API

    Sorry. Yes, I tried this. As well as another option:

    Vb Code:
    1. Private Const MS_DEF_PROV                As String = "Microsoft Base Cryptographic Provider v1.0"
    2. Private Const CRYPT_MACHINE_KEYSET       As Long = &H20

    None of it worked. I'm going to try using the OpenSSL commandline program from gnuwin32 site.

    Thank you for helping me. Maybe at some later time after a service pack or something this will suddenly work.

  20. #20

    Thread Starter
    PowerPoster
    Join Date
    Feb 2006
    Posts
    11,009

    Re: [VB6] HMAC-SHA-256, HMAC-SHA-1 Using Crypto API

    Um... &H20 is the same as 32.

    I've tested this code on a 64-bit Windows machine and it works fine there, and as you pointed out my demo program runs properly on your problem system as well.

    Turning UAC off is almost always a poor idea. You seem to be grasping at straws but so am I at this point. Without more information I don't think I can help.

  21. #21
    New Member
    Join Date
    Jan 2012
    Posts
    2

    Re: [VB6] HMAC-SHA-256, HMAC-SHA-1 Using Crypto API

    hello,i want use your project to a vba project for amazon authentication,but i donot know howto include your code to my project .can you help me?

  22. #22

    Thread Starter
    PowerPoster
    Join Date
    Feb 2006
    Posts
    11,009

    Re: [VB6] HMAC-SHA-256, HMAC-SHA-1 Using Crypto API

    Good luck with Amazon, that stuff is a bear as most Web Services are when you have to roll your own code.

    I am attaching a demo Excel Workbook. It contains basically the same thing as in the VB6 demo. The Userform is shown via a Command Button I put on Sheet1 of the Workbook.

    This doesn't try to do anything fancy, it simply shows how to use the Class from Excel. To get it there you just import the VB6 Class from within the VBA Editor IDE.

    The Class didn't require any changes, though of course the Form-to-Userform logic required a few.

    I hope this helps a little.
    Attached Files Attached Files
    Last edited by dilettante; Jan 10th, 2012 at 01:02 AM.

  23. #23
    New Member
    Join Date
    Jan 2012
    Posts
    2

    Re: [VB6] HMAC-SHA-256, HMAC-SHA-1 Using Crypto API

    Thank you . after several hours to understand how to include your class to vba project, i have attached my aim,thank you ,the hs256 class is very very very useful...

  24. #24
    New Member
    Join Date
    Apr 2012
    Posts
    6

    Re: [VB6] HMAC-SHA-256, HMAC-SHA-1 Using Crypto API

    I am trying to integrate your HS256 class into Access vba for integration into Amazon MWS and coming up with some problems.

    I have successfully created a class HS256 using the HS256.cls in v2.1 above.

    I have:

    Dim hs256 As clsHS256

    Dim bytekey() As Byte
    hs256 = New clsHS256
    bytekey = hs256.ToUTF8("MY-SECRET-KEY-HERE")
    hs256.InitHmac (bytekey) ' <----- Error on this line
    Erase bytekey

    I get an error "Type mismatch: array or user defined type expected".

    I get the same if I replace the line with
    hs256.InitHmac (bytekey(0))

    Any help any of you might be able to offer would be gratefully received. Alternatively does anyone have a working example of MWS integration into Access vba?

    Getting MWS to integrate into Access is much harder than I expected and way harder than it should be!!!

    Phill

  25. #25
    New Member
    Join Date
    Apr 2012
    Posts
    6

    Re: [VB6] HMAC-SHA-256, HMAC-SHA-1 Using Crypto API

    I worked it out myself.

    It should read:
    hs256.InitHmac bytekey

    If anyone does have a working MWS integration example Access it would still be very much appreciated!

    Phill

  26. #26

    Thread Starter
    PowerPoster
    Join Date
    Feb 2006
    Posts
    11,009

    Re: [VB6] HMAC-SHA-256, HMAC-SHA-1 Using Crypto API

    Glad you caught the problem!

    Sorry, I don't have any MWS code to share.

  27. #27

    Re: [VB6] HMAC-SHA-256, HMAC-SHA-1 Using Crypto API

    Glad with this thread dilettante, especially:
    I hope this helps.

    Going through the AWS SimpleDB documentation for REST Authentication I find the docs are good but not great. They leave out small tidbits and swing between specific and vague on important things like character encoding, what precisely they mean by "newline" and other small things. HS256 itself took some work, but figuring out the AWS "canonicalization" process is a small nightmare. They outline the steps but leaving you hanging here and there on specifics.

    They even give an example but don't show what the final Signature should be, making verification of my example here difficult.

    In any case, the example attached here is way stripped down but with copious comments. In those comments I have made notes about a few points you may need to get clarification on. Try the AWS developer support forums for answers.


    Keep in mind that different Amazon Services have different requirements. Grab all of the docs they offer (old and new) for the Service you need to use.
    It's very nice,thank you.

    Because general principle of OAuth is same (using HMAC-SHA1 or RSA-SHA1), what if made ​​into OAuth Class (clsOAuth.cls) for generate a signature (it will be very useful), so with the signature generated by OAuth class (clsOAuth.cls) we can easily access:
    1. Amazon API
    2. Twitter API
    3. Google API
    4. Facebook API
    5. etc ... API with OAuth.

    Because it's very hard to find in Google, OAuth Class created with VB6. I've tried to modify the code and make clsOAuth.cls but it always fails and displays the error message:

    HTTP/1.1 401 Unauthorized or Invalid Signature and token.

    Sorry for my english. Thank you.

  28. #28

    Thread Starter
    PowerPoster
    Join Date
    Feb 2006
    Posts
    11,009

    Re: [VB6] HMAC-SHA-256, HMAC-SHA-1 Using Crypto API

    I haven't tried working with OAuth. Have you looked at this:

    http://developer.yahoo.com/oauth/gui...h-signing.html

  29. #29
    New Member
    Join Date
    Apr 2012
    Posts
    6

    Re: [VB6] HMAC-SHA-256, HMAC-SHA-1 Using Crypto API

    I'm having a (reasonably obscure?) problem with this class. I have it integrated into Access to support integration into Amazon MWS and it is providing the signatures correctly on my development system (Access 2007 on Windows XP running under Parallels on my Mac). When I put the code onto a production environment running the runtime version of Access (32 bit) on windows 2008 server 64 bit a different (incorrect) signature is calculated and so the calls fail.

    Are there any diagnostics you could suggest I run to try to track down the problem?

    Phill

  30. #30

    Thread Starter
    PowerPoster
    Join Date
    Feb 2006
    Posts
    11,009

    Re: [VB6] HMAC-SHA-256, HMAC-SHA-1 Using Crypto API

    I tested the compiled VB6 examples and tested them on Server 2008 R2 64 bit. They work there just as expected. Server 2008 is a slightly different OS (Vista Server basically) but it shouldn't be all that different. The demos work as expected on both 32 and 64 bit Vista.

    I'd tend to blame your issues on a divergence between VB6 and VBA in later Office versions, but if it works as expected under Access 2007 32-bit running under XP we can probably ignore that possibility.

    So if it isn't at the OS and API level, and it isn't about differences between VB6 and later versions of VBA... we aren't left with many obvious things to suspect.


    I'm not sure where to start trying to diagnose this except to log intermediate values at every step of the process, then compare the logged results from both of your run time environments.

    The Encode() method may be helpful here for logging the Byte array values in hex & ascii. I'd log things to text files and then open each log in Notepad and tile them side-by-side for comparison.

  31. #31
    New Member
    Join Date
    Apr 2012
    Posts
    6

    Re: [VB6] HMAC-SHA-256, HMAC-SHA-1 Using Crypto API

    Thanks, I will do that.

    Before I start doing this please could you verify that the following routine (which I use to call your class) is calling it in the right way. In particular the last line.

    Code:
    Public Function getSignature(stringtosign As String)
        Dim bytekey() As Byte
        Dim hs256 As clsHS256
        
        Set hs256 = New clsHS256
        bytekey = hs256.ToUTF8(SecretKey)
        
        hs256.InitHmac bytekey
        Erase bytekey
        
        Dim bytecqs() As Byte
        bytecqs = hs256.ToUTF8(stringtosign)
        
        'Create the Signature hash:
        Dim byteSignature() As Byte
        byteSignature = hs256.HmacSha256(bytecqs)
        
        Erase bytecqs
            
        'Convert the Signature to Base64:
        getSignature = hs256.Encode(byteSignature, edfBase64, efNoFolding)
        
        Erase byteSignature
    
        getSignature = Left$(getSignature, Len(getSignature) - 2)
        
    End Function

  32. #32
    New Member
    Join Date
    Apr 2012
    Posts
    6

    Re: [VB6] HMAC-SHA-256, HMAC-SHA-1 Using Crypto API

    To verify things I stuck your vb RFC 4231 test routines into vba and ran on both XP with Access 2007 and on windows server 2008 64 bit with the access runtime environment. The results were identical and correct so your code works perfectly. I must be doing something wrong in the code in my earlier post.

    Phill

    My vba version of your test routines is below for completeness.

    Code:
    Option Compare Database
    
    Option Explicit
    'HMAC-SHA-256 Test vectors from RFC 4231:
    '
    '     Identifiers and Test Vectors for HMAC-SHA-224, HMAC-SHA-256,
    '                     HMAC-SHA-384, and HMAC-SHA-512
    
    Private Const TEST_KEYS As String = _
            "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b" & "0b0b0b0b|" _
          & "4a656665|" _
          & "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" & "aaaaaaaa|" _
          & "0102030405060708090a0b0c0d0e0f10" & "111213141516171819|" _
          & "0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c" & "0c0c0c0c|" _
          & "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" & "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" _
          & "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" & "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" _
          & "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" & "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" _
          & "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" & "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" _
          & "aaaaaa|" _
          & "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" & "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" _
          & "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" & "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" _
          & "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" & "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" _
          & "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" & "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" _
          & "aaaaaa"
    Private Const TEST_DATA As String = _
            "4869205468657265|" _
          & "7768617420646f2079612077616e7420" & "666f72206e6f7468696e673f|" _
          & "dddddddddddddddddddddddddddddddd" & "dddddddddddddddddddddddddddddddd" _
          & "dddddddddddddddddddddddddddddddd" & "dddd|" _
          & "cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd" & "cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd" _
          & "cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd" & "cdcd|" _
          & "546573742057697468205472756e6361" & "74696f6e|" _
          & "54657374205573696e67204c61726765" & "72205468616e20426c6f636b2d53697a" _
          & "65204b6579202d2048617368204b6579" & "204669727374|" _
          & "54686973206973206120746573742075" & "73696e672061206c6172676572207468" _
          & "616e20626c6f636b2d73697a65206b65" & "7920616e642061206c61726765722074" _
          & "68616e20626c6f636b2d73697a652064" & "6174612e20546865206b6579206e6565" _
          & "647320746f2062652068617368656420" & "6265666f7265206265696e6720757365" _
          & "642062792074686520484d414320616c" & "676f726974686d2e"
    Private Const TEST_EXPECTED As String = _
            "b0344c61d8db38535ca8afceaf0bf12b" & "881dc200c9833da726e9376c2e32cff7|" _
          & "5bdcc146bf60754e6a042426089575c7" & "5a003f089d2739839dec58b964ec3843|" _
          & "773ea91e36800e46854db8ebd09181a7" & "2959098b3ef8c122d9635514ced565fe|" _
          & "82558a389a443c0ea4cc819899f2083a" & "85f0faa3e578f8077a2e3ff46729665b|" _
          & "a3b6167473100ee06e0c796c2955552b|" _
          & "60e431591ee0b67f0d8a26aacbf5b77f" & "8e0bc6213728c5140546040f0ee37f54|" _
          & "9b09ffa71b942fcb27635fbcd5b0e944" & "bfdc63644f0713938a7f51535c3a35e2"
    Private Const TEST_DESCRIPTIONS As String = _
            "Case 1|" _
            & "Case 2 - key shorter than the length of the HMAC output|" _
            & "Case 3 - combined length of key and data > 64 bytes|" _
            & "Case 4 - combined length of key and data > 64 bytes|" _
            & "Case 5 - truncation of output to 128 bits|" _
            & "Case 6 - key larger than 128 bytes|" _
            & "Case 7 - key and data that is larger than 128 bytes"
    
    Private strKeys() As String
    Private strData() As String
    Private strExpected() As String
    Private strDescriptions() As String
    Private HS256 As clsHS256
    
    Private Function Fold(ByVal S As String) As String
        With HS256
            S = .Encode(.Decode(S), edfHexAsciiAddr, efCrLf)
        End With
        S = vbTab & Replace$(S, vbNewLine, vbNewLine & vbTab)
        Fold = Left$(S, Len(S) - 1)
    End Function
    
    Public Sub testSHAvectors()
        Dim intCase As Integer
        Dim bytSig() As Byte
        
        strKeys = Split(TEST_KEYS, "|")
        strData = Split(TEST_DATA, "|")
        strExpected = Split(TEST_EXPECTED, "|")
        strDescriptions = Split(TEST_DESCRIPTIONS, "|")
        Set HS256 = New clsHS256
        
        For intCase = 0 To 6  '1 (one) less than RFC 4231 case numbers.
                   
            logtofile (strDescriptions(intCase) & " " & vbNewLine)
            logtofile ("Key:" & vbNewLine & Fold(strKeys(intCase)))
            logtofile ("Data:" & vbNewLine & Fold(strData(intCase)))
            With HS256
                .InitHmac .Decode(strKeys(intCase))
                bytSig = .HmacSha256(.Decode(strData(intCase)))
                If intCase = 4 Then ReDim Preserve bytSig(15) 'Truncate to 128 bits ("Case 5").
                logtofile ("HmacSha256 result:" & vbNewLine _
                               & Fold(.Encode(bytSig)))
            End With
            logtofile ("Expected (RFC) result:" & vbNewLine & Fold(strExpected(intCase)))
        
        Next
    End Sub
    
    Public Sub logtofile(text As String)
    Dim bd As String
    Dim fn As String
    Dim FNum As Integer
    
    FNum = FreeFile
    bd = BaseDir()
    fn = bd & "/SIGNATURETESTS.txt"
    
    If fIsFileDIR(fn) Then
        Open fn For Append Access Write As #FNum
    Else
        Open fn For Output Access Write As #FNum
    End If
    
    Print #FNum, text; vbNewLine
    Close #FNum
    
    End Sub

  33. #33

    Thread Starter
    PowerPoster
    Join Date
    Feb 2006
    Posts
    11,009

    Re: [VB6] HMAC-SHA-256, HMAC-SHA-1 Using Crypto API

    Your calls look good.

    If the code returns the same results then we have good news and bad I guess. Sorry I couldn't be more helpful.

  34. #34
    New Member
    Join Date
    Apr 2012
    Posts
    6

    Re: [VB6] HMAC-SHA-256, HMAC-SHA-1 Using Crypto API

    OK. Have resolved it now.

    I don't understand why, but on Windows XP vba the encode method is returning the 2 extra characters CRLF at the end of the string. This is not the case for the exact same code on my copy of windows server 2008 SP2.

    I now test to see if the code is running under windows server 2008 or not, deleting the last 2 extra characters only if not and all works fine.

    In case anyone else has this pain in the future, code is below. Thanks for your advice earlier.


    Code:
    Private Type OSVERSIONINFO
        dwOSVersionInfoSize As Long
        dwMajorVersion As Long
        dwMinorVersion As Long
        dwBuildNumber As Long
        dwPlatformId As Long
        szCSDVersion As String * 128
    End Type
    
    Private Declare Function GetVersionEx Lib "kernel32" _
          Alias "GetVersionExA" (lpVersionInformation As _
          OSVERSIONINFO) As Long
    
    ' returns true if running on windows server2008
    Public Function Is2008() As Boolean
    
    Dim oOSInfo As OSVERSIONINFO
    oOSInfo.dwOSVersionInfoSize = Len(oOSInfo)
    GetVersionEx oOSInfo
    
    If oOSInfo.dwMajorVersion = 6 Then
        Is2008 = True
    Else
        Is2008 = False
    End If
    End Function
    
    Public Function getSignature(stringtosign As String) As String
        Dim bytekey() As Byte
        Dim signaturecalculated As String
        
        Set HS256 = New clsHS256
        
        bytekey = HS256.ToUTF8(SecretKey)
        
        HS256.InitHmac bytekey
        Erase bytekey
        
        Dim bytecqs() As Byte
        bytecqs = HS256.ToUTF8(stringtosign)
        
        'Create the Signature hash:
        Dim byteSignature() As Byte
        byteSignature = HS256.HmacSha256(bytecqs)
        
        Erase bytecqs
            
        'Convert the Signature to Base64:
        signaturecalculated = HS256.Encode(byteSignature, edfBase64, efNoFolding)
        
        Erase byteSignature
    
        If Not Is2008 Then
            getSignature = Left$(signaturecalculated, Len(signaturecalculated) - 2)
        Else
            getSignature = signaturecalculated
        End If
        
    End Function

  35. #35

    Thread Starter
    PowerPoster
    Join Date
    Feb 2006
    Posts
    11,009

    Re: [VB6] HMAC-SHA-256, HMAC-SHA-1 Using Crypto API

    Ok, I think that helps explain what was going wrong. The problem was in encoding the result to Base64 with no "folding."

    There are a number of things that differ between OS versions. XP uses an earlier name for the Enhanced RSA and AES Cryptographic Provider (yet at least late Server 2003 does not, could this be service packs or the R2 release?) and both XP and Server 2003 have some formatting limitations in their CryptBinaryToString() flags. The latter is why you saw a trailing CRLF when you encoded to Base64.


    Your fix will work for you, but it isn't really a general fix since Encode() can work on longer Byte arrays where you'd get CRLFs within the Base64 string as well as at the end.

    What I've done is modify the OS version sniffing logic and added a second version Boolean. Along with the new blnIsWin5_1 I've also added the kludge-code needed to accomodate these older OSs. I did the same for my HS1 class as well to head off problems for anyone using that code.

    Everything tests out good here, including a separate test program to specifically look for the problem you had found.


    The new HS256 package also includes the Excel demo, with the same update (a separate .ZIP file within the main .ZIP file). This .XLS is the large item that makes the HS256 package so big compared to the HS1 package.

    I believe these updates address the issue, but feedback is always welcome.
    Attached Files Attached Files
    Last edited by dilettante; Jan 22nd, 2013 at 09:31 PM.

  36. #36
    New Member
    Join Date
    Feb 2013
    Posts
    2

    Re: [VB6] HMAC-SHA-256, HMAC-SHA-1 Using Crypto API

    I'm running Windows 7 Ultimate

    When I run this code in VB6, I get an error "Failed to obtain CryptoAPI RSA AES context, system error -2146893799"

    This error occurs in the Class_Initialize function. GetVersionEx is returning the following values:

    dwBuildNumber = 2600
    dwMajorVersion = 5
    dwMinorVersion = 1
    dwOSVersionInfoSize = 156
    dwPlatformId = 2
    szCSDVersion = "Service Pack 3"
    wProductType = 1
    wReserved = 0
    wServicePackMajor = 3
    wServicePackMinor = 0
    wSuiteMask = 256

    Control Panel -> System and Security -> System returns the following information:
    Windows Edition: Windows 7 Ultimate, Service Pack 1
    64-bit Operating System


    I don't understand why the API would return incorrect information. Do you have any suggestions for me?

  37. #37
    New Member
    Join Date
    Feb 2013
    Posts
    2

    Re: [VB6] HMAC-SHA-256, HMAC-SHA-1 Using Crypto API

    Nevermind.

    I was running this code in the IDE, and I had configured VB6 to run in Windows XP (Service Pack 3) compatibility mode. If anyone else runs in to this issue, check your compatibility settings prior to pulling your hair out.

  38. #38

    Thread Starter
    PowerPoster
    Join Date
    Feb 2006
    Posts
    11,009

    Re: [VB6] HMAC-SHA-256, HMAC-SHA-1 Using Crypto API

    Wow, I had no idea anyone does this. It can break lots of code because of the "version lie" appcompat shim.

    As an alternative I suppose the code could try for the current crypto context name and only try the legacy XP name upon failure. But that still leaves other issues not as easily handled indirectly.

    Glad you found it though. I can see where it might get frustrating to track down.

  39. #39

    Thread Starter
    PowerPoster
    Join Date
    Feb 2006
    Posts
    11,009

    Re: [VB6] HMAC-SHA-256, HMAC-SHA-1 Using Crypto API

    Here is a demo using my HS1 class to create signatures for use with Google Maps API for Business.

    The inputs are pre-loaded with the same sample values shown at Authentication and Authorization: Signature Examples.

    One thing to note is that the sample URL there mistakenly shows braces (i.e. {}) around the value "clientID" and if you use those you will not get the proper results. This just appears to be a flaw in the posted sample URL.

    Name:  sshot.png
Views: 2535
Size:  22.0 KB


    The demo program uses multiline TextBoxes for I/O, though the values are not on multiple lines (the long text just wraps).
    Attached Files Attached Files
    Last edited by dilettante; Sep 23rd, 2013 at 11:20 AM.

  40. #40

    Thread Starter
    PowerPoster
    Join Date
    Feb 2006
    Posts
    11,009

    Re: [VB6] HMAC-SHA-256, HMAC-SHA-1 Using Crypto API

    I have added another rendition of the Google Maps API for Business "signer" logic.

    Testing code and such have been removed, redundant intermediate variables have been removed, and more formalized URL parsing is used. The result is probably more directly usable in real applications.

    Here we have a class GoogleMapsSigner with a single method Sign(). It is dependent on the HS1 class.

    To use these in VB6 just add both class modules to your Project. They should also import into Office VBA easily enough as well (Access, Excel) but have not been tested in 64-bit Office applications which might require tweaking due to the changes in integer types there.


    The attachment has both of the necessary class modules as well as a test Project similar to the one above.
    Attached Files Attached Files

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Featured


Click Here to Expand Forum to Full Width

Survey posted by VBForums.