2

I am building a VB.Net WCF client to access an Axis web service. I have already found a lot of great help with creating the Security Header which is not described in the WSDL. This is based on the OASIS specifications and very similar to this question. However, I have found a number of C# solutions which describe generating the Nonce and Password Digest, but I can't see what I am doing wrong. I based my implementation on this article.

Here is my code for generating and validating the Nonce and PasswordDigest:

Public Function GetPasswordDigestAsBase64() As String
    'Nonce is already generated as a cryptographically strong random value
    Dim sRetval As String = ""

    'Get other operands to the right format
    Dim time As Byte() = Encoding.UTF8.GetBytes(GetCreatedAsString())
    Dim pwd As Byte() = Encoding.UTF8.GetBytes(SystemPassword)
    Dim operand As Byte() = New Byte(_nonce.Length + time.Length + pwd.Length - 1) {}
    Array.Copy(_nonce, operand, _nonce.Length)
    Array.Copy(time, 0, operand, _nonce.Length, time.Length)
    Array.Copy(pwd, 0, operand, _nonce.Length + time.Length, pwd.Length)

    ' create the hash
    Dim sha As SHA1 = SHA1.Create()
    sRetval = Convert.ToBase64String(sha.ComputeHash(operand))
    'If ValidateToken(sRetval, GetNonceAsBase64, GetCreatedAsString) Then
    '    Dim sDebug As String = "Yes"
    'Else
    '    Dim sFail As String = "No"
    'End If
    Return sRetval
End Function

Public Function ValidateToken(password As String, sNonceAsBase64 As String, sCreated As String) As Boolean
    'Convert Nonce
    Dim testNonce As Byte() = Convert.FromBase64String(sNonceAsBase64)
    Dim pwd As Byte() = Encoding.UTF8.GetBytes(ConfigurationManager.AppSettings("Password"))
    'Dim pwd As Byte() = Encoding.UTF8.GetBytes(password)
    Dim createdBytes As Byte() = Encoding.UTF8.GetBytes(sCreated)
    Dim operand As Byte() = New Byte(testNonce.Length + createdBytes.Length + (pwd.Length - 1)) {}
    Array.Copy(testNonce, operand, testNonce.Length)
    Array.Copy(createdBytes, 0, operand, testNonce.Length, createdBytes.Length)
    Array.Copy(pwd, 0, operand, testNonce.Length + createdBytes.Length, pwd.Length)
    Dim sha1__1 As SHA1 = SHA1.Create()
    Dim trueDigest As String = Convert.ToBase64String(sha1__1.ComputeHash(operand))

    Return [String].Compare(trueDigest, password) = 0
End Function

My nonce is defined for the class as: Private _nonce As Byte() = New Byte(15) {}

It is populated like so:

    Dim rndGenerator As RandomNumberGenerator = New RNGCryptoServiceProvider()
    rndGenerator.GetBytes(_nonce)

I can generate my PasswordDigest and "un-hash" it with the ValidateToken formula, but I cannot Validate a "known-good" example from the vendor by taking their PasswordDigest, and attempting to re-make it from the shared password, Created time and nonce as base 64. That indicates to me that we are using different algorithms for the Digest.

Does anyone know of a VB.Net example for this or could I get some pointers as to what I'm doing wrong? I'm thinking I must have gotten something wrong with my understanding of the formula Digest = Base64(SHA1(nonce + created + password))

My nonce is 16 bytes. Here is the redacted security header:

    <wsse:Security s:mustUnderstand="1" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<wsu:Timestamp wsu:Id="TS-2"> 
<wsu:Created>2015-02-18T15:20:16.000Z</wsu:Created>
<wsu:Expires>2015-02-18T15:25:16.000Z</wsu:Expires>
</wsu:Timestamp>
<wsse:UsernameToken wsu:Id="UsernameToken-1">
<wsse:Username>MyUserName</wsse:Username>          
<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest">MyPassHashed</wsse:Password>          
<wsse:Nonce EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">5VlfBQDItoCHHx3xmWikEg==</wsse:Nonce>          
<wsu:Created>2015-02-18T15:20:16.000Z</wsu:Created>        
</wsse:UsernameToken>      
</wsse:Security>

The specific error I get is that: WSDoAllReceiver: security processing failed error That tells me that I have my certificate, firewall and routing worked out, I'm reaching the service and getting a response from their service.

Thank you in advance for any help with this.

Community
  • 1
  • 1
ja928
  • 428
  • 3
  • 16

0 Answers0